Compare commits

...
66 Commits
Author SHA1 Message Date
steve c66d319d9c UPdate to 20021027 snapshot. 2002-10-28 02:26:41 +00:00
steve ae27165ffe Add Virtex code generators for left shift,
subtraction, and GE comparators.
2002-10-28 02:05:56 +00:00
steve 32f1ca6f8b draw lpm ff with aset_expr taken into account. 2002-10-23 04:39:35 +00:00
steve 9ce2806710 Fix synth2 handling of aset/aclr signals where
flip-flops are split by begin-end blocks.
2002-10-23 01:45:24 +00:00
steve 3d4593d4d5 Synthesizer support for synchronous begin-end blocks. 2002-10-21 01:42:08 +00:00
steve df5ae54ec7 Handle conditional error cases better. 2002-10-20 19:19:37 +00:00
steve fbee1b424d Properly set or clear expression lookaside for binary expressions. 2002-10-20 02:55:37 +00:00
steve 555017b525 Snapshot 20021019 2002-10-19 23:38:49 +00:00
steve 1e170ee005 bourne shell compatibility. 2002-10-19 23:18:52 +00:00
steve 43501809b1 Redo the parameter vector support to allow
parameter names in range expressions.
2002-10-19 22:59:49 +00:00
steve c0c67a101a Fix spelling of the scalared keyword. 2002-10-13 05:01:44 +00:00
steve 1eb714e097 More verbose eval_const assert message. 2002-10-13 05:01:07 +00:00
steve 54a8e12856 Fix symbol underscore needs for Mac OS X. 2002-10-03 18:03:35 +00:00
steve 6203f05ef9 Add pal target enable help message. 2002-10-03 17:57:54 +00:00
steve 703ad04067 Allow expression lookaside map to spam statements. 2002-09-27 20:24:42 +00:00
steve 778e96330d Add thread expression lookaside map. 2002-09-27 16:33:34 +00:00
steve e3eb89fb12 Remove excess debug messages. 2002-09-26 03:42:10 +00:00
steve 166621bcb3 Generate vvp code for asynch set/reset of NetFF. 2002-09-26 03:18:04 +00:00
steve 879a5a4cbe Synthesize async set/reset is certain cases. 2002-09-26 01:13:14 +00:00
steve 9faabfe995 Fix missing endifs within supressed ifdefs. 2002-09-25 02:23:08 +00:00
steve 6f23fa61ac Allow results in register bits 47 in certain cases. 2002-09-24 04:20:32 +00:00
steve 30b6cf7821 Include user specified libraries on the link line. 2002-09-24 01:50:53 +00:00
steve 6258011210 More detailed check of process edge events. 2002-09-24 00:58:35 +00:00
steve 7557a46382 Remove some now useless asserts. 2002-09-21 23:47:30 +00:00
steve a0a91f358c Snapshot 20020921 2002-09-21 21:29:09 +00:00
steve 0128286966 Allow constant bit selects out of range. 2002-09-21 21:28:18 +00:00
steve acd5e86e04 Fix disable in arbitrary fork/join situations. 2002-09-21 04:55:00 +00:00
steve ab94b0a636 disable threads with children. 2002-09-20 03:59:34 +00:00
steve de6d696667 Add support for cbAfterDelay. 2002-09-20 02:42:11 +00:00
steve 63946c4cfb More careful cd command. 2002-09-20 02:41:36 +00:00
steve 475b603d15 Relax position constrations of ifdef and friends. 2002-09-19 20:33:27 +00:00
steve 096956cda9 Fix multiple source on the command line. 2002-09-18 23:25:18 +00:00
steve 3d3116d48b Add support for binary NOR operator. 2002-09-18 04:29:55 +00:00
steve 616360d751 Spelling errors. 2002-09-18 04:08:45 +00:00
steve 7a5c30d297 printf size warning. 2002-09-18 03:34:07 +00:00
steve 9c5ab36a8b Fix switch case warnings. 2002-09-18 03:33:10 +00:00
steve 466656b167 Allow forward references of memories. 2002-09-18 02:55:18 +00:00
steve 5d6567cb02 Generate vvp code for structural flip-flops. 2002-09-17 05:37:45 +00:00
steve c44c123ef5 Connect output of block to net_out, instead of statement outputs. 2002-09-17 04:40:28 +00:00
steve 4ecbf56e2b Account for part select in l-value. 2002-09-17 04:39:20 +00:00
steve ed9a2c4b3f Proper initialization of the memories table. 2002-09-17 00:42:22 +00:00
steve 90751b9250 Reject multiple probes on synchronous logic. 2002-09-16 21:55:06 +00:00
steve 7d8011669d snapshot 20020915 2002-09-16 03:48:56 +00:00
steve eb81062d85 Add to synth2 support for synthesis of
synchronous logic. This includes DFF enables
 modeled by if/then/else.
2002-09-16 00:30:33 +00:00
steve 8fbacc966e compile error. 2002-09-16 00:28:51 +00:00
steve 75801a12e3 Display FF enables. 2002-09-16 00:28:25 +00:00
steve 9f1ce170e6 Generate code for 8:1 muxes msing F5 and F6 muxes. 2002-09-15 21:52:19 +00:00
steve 327c8826f4 Generate Virtex code for 4:1 mux slices. 2002-09-14 05:19:19 +00:00
steve fb0383d2bd single bit optimization for != in expressions,
and expand ++ and != results if needed.
2002-09-13 04:09:51 +00:00
steve 28725d0d74 Optimize ==1 when in context where x vs z doesnt matter. 2002-09-13 03:12:50 +00:00
steve dac99b9374 Add support for binary nand operator. 2002-09-12 15:49:43 +00:00
steve 1573477caf Account for buffer overrun in memory word names. 2002-09-12 15:13:07 +00:00
steve 70a7513781 Support $ in preprocessor identifiers. 2002-09-11 19:42:37 +00:00
steve 0277035496 Fix wrecked rbuf in vpi_get_str of signals and memories. 2002-09-11 16:06:57 +00:00
steve 33f462fdf6 Actually set strength pointer when getting strength val. 2002-09-10 02:27:11 +00:00
steve 639b9f346f Snapshot 20020907 2002-09-08 01:39:23 +00:00
steve 447fee6f43 Fix padding of operand of unary minus. 2002-09-08 01:37:13 +00:00
steve c9212a9a09 Implement vpi_remove_cb for cbValueChange. 2002-09-07 04:54:51 +00:00
steve ea21fab379 Add support for %v is the display system task.
Change the encoding of H and L outputs from
 the bufif devices so that they are logic x.
2002-09-06 04:56:28 +00:00
steve 4d090b64bd List tran devices as unsupported. 2002-09-04 16:19:39 +00:00
steve 7e1e44e87a Properly cast signedness of parameters with ranges. 2002-09-01 03:01:48 +00:00
steve 0a2a9dcd94 Fix leaking vthread bits in ?: eval. 2002-09-01 01:42:34 +00:00
steve c9b4b66af2 Watch for x indices in l-value of non-blocking assignments. 2002-09-01 00:19:35 +00:00
steve 7b6678b2a1 Fix reverse bit ordered bit select in continuous assignment. 2002-08-31 03:48:50 +00:00
steve e79f62c5fa Generate x out for x select on wide muxes. 2002-08-29 03:04:01 +00:00
steve 60046cc790 update for 20020828 snapshot. 2002-08-28 20:30:53 +00:00
64 changed files with 3410 additions and 880 deletions
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.133 2002/08/12 00:27:10 steve Exp $"
#ident "$Id: Makefile.in,v 1.134 2002/09/16 00:30:33 steve Exp $"
#
#
SHELL = /bin/sh
@@ -126,7 +126,7 @@ net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o \
set_width.o sync.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o \
+3
View File
@@ -307,6 +307,9 @@ constructs.
- trireg is not supported. tri0 and tri1 are supported.
- tran primitives, i.e. tran, tranif1, tranif0, rtran, rtranif1
and rtranif0 are not supported.
- Module instance arrays are not supported, although gate instance
arrays do work.
+1 -1
View File
@@ -12,7 +12,7 @@ autoconf
for dir in vpip vvp tgt-vvp tgt-fpga libveriuser
do
echo "Autoconf in $dir..."
( cd $dir ; autoconf )
( cd ./$dir ; autoconf )
done
echo "Precompiling lexor_keyword.gperf"
+59 -61
View File
@@ -46,7 +46,8 @@ do_times=no
AC_MSG_RESULT($do_times)
AC_CHECK_HEADER(ipal.h, HAVE_IPAL=yes, HAVE_IPAL=)
AC_ARG_WITH(ipal,enable PAL target,
AC_ARG_WITH(ipal,
[ --with-ipal enable PAL target],
if test "$with_ipal" = no; then
echo Disabling ipal support
HAVE_IPAL=
@@ -74,66 +75,6 @@ AC_LANG_C
AC_CANONICAL_HOST
# $host
#######################
## test for underscores. The vpi module loader needs to know this
## in order to know the name of the start symbol for the .vpi module.
#######################
AC_CYGWIN
AC_EXEEXT
AC_MINGW32
WIN32=no
AC_MSG_CHECKING("Checking for windows")
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
then
WIN32=yes
fi
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
AC_SUBST(EXEEXT)
AC_MSG_CHECKING("for leading and/or trailing underscores")
cat << EOF > underscore.c
void underscore(void){}
EOF
$CC -shared -c underscore.c > /dev/null 2>&1
CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
output=`nm underscore.o|grep underscore_ 2>&1`
if test ! -z "$output"; then
CC_TRAILING_UNDERSCORE=yes
AC_DEFINE(NEED_TU)
fi
if test "$CC_LEADING_UNDERSCORE" = yes; then
AC_DEFINE(WLU)
fi
if test "$CC_TRAILING_UNDERSCORE" = yes; then
AC_DEFINE(WTU)
fi
rm underscore.c underscore.o
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
#######################
## end of test for underscores
#######################
# The -fPIC flag is used to tell the compiler to make position
# independent code. It is needed when making shared objects.
@@ -233,6 +174,63 @@ esac
AC_SUBST(shared)
AC_MSG_RESULT($shared)
#######################
## test for underscores. The vpi module loader needs to know this
## in order to know the name of the start symbol for the .vpi module.
#######################
AC_CYGWIN
AC_EXEEXT
AC_MINGW32
WIN32=no
AC_MSG_CHECKING("Checking for windows")
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
then
WIN32=yes
fi
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
AC_SUBST(EXEEXT)
AC_MSG_CHECKING("for leading and/or trailing underscores")
cat << EOF > underscore.c
void underscore(void){}
EOF
$CC $shared -c underscore.c > /dev/null 2>&1
CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -o $WIN32 = "yes"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
output=`nm underscore.o|grep underscore_ 2>&1`
if test ! -z "$output"; then
CC_TRAILING_UNDERSCORE=yes
AC_DEFINE(NEED_TU)
fi
if test "$CC_LEADING_UNDERSCORE" = yes; then
AC_DEFINE(WLU)
fi
if test "$CC_TRAILING_UNDERSCORE" = yes; then
AC_DEFINE(WTU)
fi
rm underscore.c underscore.o
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
#######################
## end of test for underscores
#######################
AC_MSG_CHECKING("for ident support in C compiler")
ident_support='-DHAVE_CVS_IDENT=1'
+28 -7
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.133 2002/08/19 00:06:11 steve Exp $"
#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -271,7 +271,8 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
void NetFF::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_FF: " << name()
<< " scope=" << (scope()? scope()->name() : "") << endl;
<< " scope=" << (scope()? scope()->name() : "")
<< " aset_value=" << aset_value_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -699,17 +700,26 @@ void NetScope::dump(ostream&o) const
/* Dump the parameters for this scope. */
{
map<string,NetExpr*>::const_iterator pp;
map<string,param_expr_t>::const_iterator pp;
for (pp = parameters_.begin()
; pp != parameters_.end() ; pp ++) {
o << " parameter " << (*pp).first << " = " <<
*(*pp).second << ";" << endl;
o << " parameter ";
if ((*pp).second.signed_flag)
o << "signed ";
if ((*pp).second.msb)
o << "[" << *(*pp).second.msb
<< ":" << *(*pp).second.lsb << "] ";
o << (*pp).first << " = " <<
*(*pp).second.expr << ";" << endl;
}
for (pp = localparams_.begin()
; pp != localparams_.end() ; pp ++) {
o << " localparam " << (*pp).first << " = " <<
*(*pp).second << ";" << endl;
*(*pp).second.expr << ";" << endl;
}
}
@@ -925,7 +935,10 @@ void NetEMemory::dump(ostream&o) const
void NetEParam::dump(ostream&o) const
{
o << "<" << scope_->name() << "." << name_ << ">";
if (scope_ != 0)
o << "<" << scope_->name() << "." << name_ << ">";
else
o << "<" << name_ << ">";
}
void NetETernary::dump(ostream&o) const
@@ -991,6 +1004,14 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.135 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.134 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.133 2002/08/19 00:06:11 steve
* Allow release to handle removal of target net.
*
+26 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.63 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
#endif
# include "config.h"
@@ -120,7 +120,8 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case '^':
case '&':
case '|':
case 'O':
case 'O': // NOR (~|)
case 'A': // NAND (~&)
case 'X':
tmp = new NetEBBits(op_, lp, rp);
tmp->set_line(*this);
@@ -632,11 +633,21 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
unsigned idx = net->sb_to_idx(msv);
if (idx >= net->pin_count()) {
cerr << get_line() << ": internal error: "
<< "bit " << msv << " out of range of net "
/* The bit select is out of range of the
vector. This is legal, but returns a
constant 1'bx value. */
verinum x (verinum::Vx);
NetEConst*tmp = new NetEConst(x);
tmp->set_line(*this);
cerr << get_line() << ": warning: Bit select ["
<< msv << "] out of range of vector "
<< net->name() << "[" << net->msb()
<< ":" << net->lsb() << "]." << endl;
return 0;
cerr << get_line() << ": : Replacing "
<< "expression with a constant 1'bx." << endl;
delete msn;
return tmp;
}
NetESignal*tmp = new NetESignal(net, idx, idx);
@@ -697,7 +708,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
assert(idx_ == 0);
NetExpr*i = msb_->elaborate_expr(des, scope);
if (msb_ && i == 0) {
cerr << get_line() << ": error: Unable to exaborate "
cerr << get_line() << ": error: Unable to elaborate "
"index expression `" << *msb_ << "'" << endl;
des->errors += 1;
return 0;
@@ -874,6 +885,15 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/*
* $Log: elab_expr.cc,v $
* Revision 1.66 2002/09/21 21:28:18 steve
* Allow constant bit selects out of range.
*
* Revision 1.65 2002/09/18 04:08:45 steve
* Spelling errors.
*
* Revision 1.64 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.63 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
+66 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.97 2002/08/21 02:28:03 steve Exp $"
#ident "$Id: elab_net.cc,v 1.101 2002/09/18 04:29:55 steve Exp $"
#endif
# include "config.h"
@@ -67,6 +67,8 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
case '|': // Bitwise OR
case '&':
case '^':
case 'A': // Bitwise NAND (~&)
case 'O': // Bitwise NOR (~|)
case 'X': // Exclusing NOR
return elaborate_net_bit_(des, scope, width, rise, fall, decay);
case 'E': // === (case equals)
@@ -340,6 +342,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
}
break;
case 'A': // NAND (~&)
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
3, NetLogic::NAND);
connect(gate->pin(1), lsig->pin(idx));
connect(gate->pin(2), rsig->pin(idx));
connect(gate->pin(0), osig->pin(idx));
gate->rise_time(rise);
gate->fall_time(fall);
gate->decay_time(decay);
des->add_node(gate);
}
break;
case '|': // Bitwise OR
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
@@ -354,6 +370,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
}
break;
case 'O': // Bitwise NOR
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
3, NetLogic::NOR);
connect(gate->pin(1), lsig->pin(idx));
connect(gate->pin(2), rsig->pin(idx));
connect(gate->pin(0), osig->pin(idx));
gate->rise_time(rise);
gate->fall_time(fall);
gate->decay_time(decay);
des->add_node(gate);
}
break;
default:
assert(0);
}
@@ -1173,7 +1203,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
}
/*
* This provate method handles the special case that we have a
* This private method handles the special case that we have a
* non-constant bit-select of an identifier. We already know that the
* signal that is represented is "sig".
*/
@@ -1188,12 +1218,25 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
/* Elaborate the selector. */
NetNet*sel = msb_->elaborate_net(des, scope, 0, 0, 0, 0);
unsigned sig_width = sig->pin_count();
NetMux*mux = new NetMux(scope, scope->local_hsymbol(), 1,
sig->pin_count(),
sel->pin_count());
sig_width, sel->pin_count());
for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1)
connect(mux->pin_Data(0, idx), sig->pin(idx));
/* Connect the signal bits to the mux. Account for the
direction of the numbering (lsb to msb vs. msb to lsb) by
swapping the connection order. */
if (sig->msb() > sig->lsb()) {
sel = add_to_net(des, sel, -sig->lsb());
for (unsigned idx = 0 ; idx < sig_width ; idx += 1)
connect(mux->pin_Data(0, idx), sig->pin(idx));
} else {
sel = add_to_net(des, sel, -sig->msb());
for (unsigned idx = 0 ; idx < sig_width ; idx += 1)
connect(mux->pin_Data(0, idx), sig->pin(sig_width-idx-1));
}
for (unsigned idx = 0 ; idx < sel->pin_count() ; idx += 1)
connect(mux->pin_Sel(idx), sel->pin(idx));
@@ -2078,9 +2121,12 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
case '-': // Unary 2's complement.
sig = new NetNet(scope, scope->local_hsymbol(),
NetNet::WIRE, sub_sig->pin_count());
NetNet::WIRE, owidth);
sig->local_flag(true);
if (sub_sig->pin_count() < owidth)
sub_sig = pad_to_width(des, sub_sig, owidth);
switch (sub_sig->pin_count()) {
case 0:
assert(0);
@@ -2161,6 +2207,18 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.101 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.100 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.99 2002/09/08 01:37:13 steve
* Fix padding of operand of unary minus.
*
* Revision 1.98 2002/08/31 03:48:50 steve
* Fix reverse bit ordered bit select in continuous assignment.
*
* Revision 1.97 2002/08/21 02:28:03 steve
* Carry mux output delays.
*
+34 -28
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.15 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -64,13 +64,21 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
scope->set_parameter((*cur).first, new NetEParam);
NetEParam*tmp = new NetEParam;
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
scope->set_parameter((*cur).first, new NetEParam);
NetEParam*tmp = new NetEParam;
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
@@ -86,6 +94,9 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = false;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
@@ -93,30 +104,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
parameter value is coerced to have the correct
and defined width. */
if ((*cur).second.msb) {
verinum*msb = (*cur).second.msb ->eval_const(des, scope);
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
assert(msb);
verinum*lsb = (*cur).second.lsb ->eval_const(des, scope);
assert(lsb);
long msl = msb->as_long();
long lsl = lsb->as_long();
delete msb;
delete lsb;
unsigned width;
if (msl >= lsl)
width = msl - lsl + 1;
else
width = lsl - msl + 1;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(val)) {
verinum tval (tmp->value(), width);
val = new NetEConst(tval);
delete tmp;
}
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
signed_flag = (*cur).second.signed_flag;
}
val = scope->set_parameter((*cur).first, val);
val->cast_signed(signed_flag);
val = scope->set_parameter((*cur).first, val,
msb, lsb, signed_flag);
assert(val);
delete val;
}
@@ -128,7 +124,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
val = scope->set_parameter((*cur).first, val);
val = scope->set_parameter((*cur).first, val, 0, 0, false);
assert(val);
delete val;
}
@@ -336,9 +332,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
PExpr*tmp = (*cur).second;
NetExpr*val = tmp->elaborate_pexpr(des, sc);
val = my_scope->set_parameter((*cur).first, val);
assert(val);
delete val;
bool flag = my_scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< (*cur).first << " not found in "
<< sc->name() << "." << endl;
}
}
}
@@ -497,6 +496,13 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.17 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.16 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
* Revision 1.15 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
+15 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval.cc,v 1.30 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: eval.cc,v 1.32 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -143,6 +143,13 @@ verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
return 0;
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
if (eval == 0) {
cerr << get_line() << ": internal error: Unable to evaluate "
<< "constant expression (parameter=" << path_
<< "): " << *expr << endl;
return 0;
}
assert(eval);
if (msb_ || lsb_)
@@ -219,6 +226,13 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
/*
* $Log: eval.cc,v $
* Revision 1.32 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.31 2002/10/13 05:01:07 steve
* More verbose eval_const assert message.
*
* Revision 1.30 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+6 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_tree.cc,v 1.41 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.42 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -884,7 +884,7 @@ NetExpr* NetEParam::eval_tree()
// The result can be saved as the value of the parameter for
// future reference, and return a copy to the caller.
scope_->set_parameter(name_.peek_name(0), res);
scope_->replace_parameter(name_.peek_name(0), res);
return res->dup_expr();
}
@@ -1134,6 +1134,10 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.42 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.41 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+6 -8
View File
@@ -17,7 +17,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.6 2002/07/05 17:17:20 steve Exp $"
#ident "$Id: iverilog-vpi.sh,v 1.9 2002/10/19 23:18:52 steve Exp $"
# These are the variables used for compiling files
CC=gcc
@@ -44,13 +44,13 @@ do
case $parm
in
*.c) CCSRC="$SRC $parm"
*.c) CCSRC="$CCSRC $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .c`
fi
;;
*.cc) CXSRC="$SRC $parm"
*.cc) CXSRC="$CXSRC $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .cc`
fi
@@ -84,8 +84,7 @@ OUT=$OUT".vpi"
compile_errors=0
# Compile all the source files into object files
for src
in $CCSRC
for src in $CCSRC
do
base=`basename $src .c`
obj=$base".o"
@@ -95,8 +94,7 @@ do
OBJ="$OBJ $obj"
done
for src
in $CXSRC
for src in $CXSRC
do
base=`basename $src .cc`
obj=$base".o"
@@ -113,4 +111,4 @@ then
fi
echo "Making $OUT from $OBJ..."
exec $LD -o $OUT $LDFLAGS $OBJ $LDLIBS
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
+3
View File
@@ -54,6 +54,9 @@ ivl_logic_pin
ivl_logic_pins
ivl_logic_udp
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data
+24 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.105 2002/08/24 05:03:40 steve Exp $"
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
#endif
#ifdef __cplusplus
@@ -418,7 +418,15 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
*
* ivl_expr_width
* This method returns the bit width of the expression at this
* node. It can be applied to any expression node.
* node. It can be applied to any expression node, and returns the
* *output* width of the expression node.
*
* ivl_expr_opcode
* IVL_EX_BINARY and IVL_EX_UNARY expression nodes include an
* upcode from this table:
* & -- AND
* A -- NAND (~&)
* X -- XNOR (~^)
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
@@ -604,6 +612,10 @@ extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net);
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
extern unsigned ivl_lpm_width(ivl_lpm_t net);
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
@@ -1079,6 +1091,16 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.108 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.107 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.106 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.105 2002/08/24 05:03:40 steve
* Missing declaration of ivl_memory_scope.
*
+12 -12
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.32 2002/04/04 05:26:13 steve Exp $"
#ident "$Id: lexor.lex,v 1.35 2002/09/25 02:23:08 steve Exp $"
#endif
# include "config.h"
@@ -170,7 +170,7 @@ W [ \t\b\f]+
directive and the name, go into PPDEFINE mode and prepare to
collect the defined value. */
`define{W}[a-zA-Z_][a-zA-Z0-9_]*{W}? { yy_push_state(PPDEFINE); def_start(); }
`define{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}? { yy_push_state(PPDEFINE); def_start(); }
<PPDEFINE>.* {
do_define();
@@ -194,7 +194,7 @@ W [ \t\b\f]+
yy_pop_state();
}
`undef{W}[a-zA-Z_][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
`undef{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}?.* { def_undefine(); }
/* Detect conditional compilation directives, and parse them. If I
@@ -206,7 +206,7 @@ W [ \t\b\f]+
condition that stacks on top of the IFDEF_FALSE so that output is
not accidentally turned on within nested ifdefs. */
^{W}?`ifdef{W}[a-zA-Z_][a-zA-Z0-9_]* {
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char*name = strchr(yytext, '`');
assert(name);
name += 6;
@@ -219,7 +219,7 @@ W [ \t\b\f]+
}
}
^{W}?`ifndef{W}[a-zA-Z_][a-zA-Z0-9_]* {
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char*name = strchr(yytext, '`');
assert(name);
name += 7;
@@ -232,22 +232,22 @@ W [ \t\b\f]+
}
}
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifdef{W}.* { yy_push_state(IFDEF_SUPR); }
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifndef{W}.* { yy_push_state(IFDEF_SUPR); }
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} { yy_push_state(IFDEF_SUPR); }
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { yy_push_state(IFDEF_SUPR); }
<IFDEF_TRUE>{W}?`else { BEGIN(IFDEF_FALSE); }
<IFDEF_FALSE>{W}?`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>{W}?`else { }
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else { }
<IFDEF_FALSE,IFDEF_SUPR>. { }
<IFDEF_FALSE,IFDEF_SUPR>\n { istack->lineno += 1; fputc('\n', yyout); }
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>^{W}?`endif {
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif {
yy_pop_state();
}
/* This pattern notices macros and arranges for them to be replaced. */
`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
/* Any text that is not a directive just gets passed through to the
output. Very easy. */
+1 -1
View File
@@ -82,7 +82,7 @@ rpmos, K_rpmos
rtran, K_rtran
rtranif0, K_rtranif0
rtranif1, K_rtranif1
scalered, K_scalered
scalared, K_scalared
signed, K_signed
small, K_small
specify, K_specify
+125 -109
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000Stephen Williams ([email protected])
* Copyright (c) 2000-2002 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_design.cc,v 1.27 2002/08/16 05:18:27 steve Exp $"
#ident "$Id: net_design.cc,v 1.28 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -242,13 +242,11 @@ void NetScope::run_defparams(Design*des)
continue;
}
NetExpr*tmp = targ_scope->set_parameter(name, val);
if (tmp == 0) {
bool flag = targ_scope->replace_parameter(name, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< name << " not found in " << targ_scope->name()
<< "." << endl;
} else {
delete tmp;
<< name << " not found in "
<< targ_scope->name() << "." << endl;
}
delete[]name;
@@ -276,34 +274,129 @@ void NetScope::evaluate_parameters(Design*des)
// scanning code. Now the parameter expression can be fully
// evaluated, or it cannot be evaluated at all.
typedef map<string,NetExpr*>::iterator mparm_it_t;
typedef map<string,param_expr_t>::iterator mparm_it_t;
for (mparm_it_t cur = parameters_.begin()
; cur != parameters_.end() ; cur ++) {
// Get the NetExpr for the parameter.
NetExpr*expr = (*cur).second;
assert(expr);
long msb = 0;
long lsb = 0;
bool range_flag = false;
NetExpr*expr;
// If it's already a NetEConst, then this parameter is done.
if (dynamic_cast<const NetEConst*>(expr))
continue;
/* Evaluate the msb expression, if it is present. */
expr = (*cur).second.msb;
// Try to evaluate the expression.
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second->get_line() << ": internal error: "
"unable to evaluate parm expression: " <<
*expr << endl;
des->errors += 1;
continue;
if (expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
if (! tmp) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.msb = nexpr;
tmp = dynamic_cast<NetEConst*>(nexpr);
}
assert(tmp);
msb = tmp->value().as_long();
range_flag = true;
}
// The evaluate worked, replace the old expression with
// this constant value.
assert(nexpr);
delete expr;
(*cur).second = nexpr;
/* Evaluate the lsb expression, if it is present. */
expr = (*cur).second.lsb;
if (expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
if (! tmp) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.lsb = nexpr;
tmp = dynamic_cast<NetEConst*>(nexpr);
}
assert(tmp);
lsb = tmp->value().as_long();
assert(range_flag);
}
/* Evaluate the parameter expression, if necessary. */
expr = (*cur).second.expr;
assert(expr);
if (! dynamic_cast<const NetEConst*>(expr)) {
// Try to evaluate the expression.
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
"unable to evaluate parameter value: " <<
*expr << endl;
des->errors += 1;
continue;
}
// The evaluate worked, replace the old expression with
// this constant value.
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
// Set the signedness flag.
(*cur).second.expr->cast_signed( (*cur).second.signed_flag );
}
/* If the parameter has range information, then make
sure the value is set right. */
if (range_flag) {
long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
assert(val);
verinum value = val->value();
if (! (value.has_len()
&& (value.len() == wid)
&& (value.has_sign() == (*cur).second.signed_flag))) {
verinum tmp (value, wid);
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
(*cur).second.expr = val;
}
}
}
}
@@ -500,6 +593,10 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.28 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.27 2002/08/16 05:18:27 steve
* Fix intermix of node functors and node delete.
*
@@ -518,86 +615,5 @@ void Design::delete_process(NetProcTop*top)
*
* Revision 1.22 2001/10/20 05:21:51 steve
* Scope/module names are char* instead of string.
*
* Revision 1.21 2001/10/19 21:53:24 steve
* Support multiple root modules (Philip Blundell)
*
* Revision 1.20 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.19 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.18 2001/01/14 23:04:56 steve
* Generalize the evaluation of floating point delays, and
* get it working with delay assignment statements.
*
* Allow parameters to be referenced by hierarchical name.
*
* Revision 1.17 2000/12/16 01:45:48 steve
* Detect recursive instantiations (PR#2)
*
* Revision 1.16 2000/09/24 17:41:13 steve
* fix null pointer when elaborating undefined task.
*
* Revision 1.15 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.14 2000/08/12 17:59:48 steve
* Limit signal scope search at module boundaries.
*
* Revision 1.13 2000/07/30 18:25:43 steve
* Rearrange task and function elaboration so that the
* NetTaskDef and NetFuncDef functions are created during
* signal enaboration, and carry these objects in the
* NetScope class instead of the extra, useless map in
* the Design class.
*
* Revision 1.12 2000/07/23 02:41:32 steve
* Excessive assert.
*
* Revision 1.11 2000/07/22 22:09:03 steve
* Parse and elaborate timescale to scopes.
*
* Revision 1.10 2000/07/16 04:56:08 steve
* Handle some edge cases during node scans.
*
* Revision 1.9 2000/07/14 06:12:57 steve
* Move inital value handling from NetNet to Nexus
* objects. This allows better propogation of inital
* values.
*
* Clean up constant propagation a bit to account
* for regs that are not really values.
*
* Revision 1.8 2000/05/02 16:27:38 steve
* Move signal elaboration to a seperate pass.
*
* Revision 1.7 2000/05/02 03:13:31 steve
* Move memories to the NetScope object.
*
* Revision 1.6 2000/05/02 00:58:12 steve
* Move signal tables to the NetScope class.
*
* Revision 1.5 2000/04/28 16:50:53 steve
* Catch memory word parameters to tasks.
*
* Revision 1.4 2000/04/10 05:26:06 steve
* All events now use the NetEvent class.
*
* Revision 1.3 2000/03/11 03:25:52 steve
* Locate scopes in statements.
*
* Revision 1.2 2000/03/10 06:20:48 steve
* Handle defparam to partial hierarchical names.
*
* Revision 1.1 2000/03/08 04:36:53 steve
* Redesign the implementation of scopes and parameters.
* I now generate the scopes and notice the parameters
* in a separate pass over the pform. Once the scopes
* are generated, I can process overrides and evalutate
* paremeters before elaboration begins.
*
*/
+32 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_expr.cc,v 1.6 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_expr.cc,v 1.8 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -110,6 +110,30 @@ unsigned NetEConcat::repeat() const
return repeat_value_;
}
NetEParam::NetEParam()
: des_(0), scope_(0)
{
}
NetEParam::NetEParam(Design*d, NetScope*s, const hname_t&n)
: des_(d), scope_(s), name_(n)
{
}
NetEParam::~NetEParam()
{
}
bool NetEParam::has_width() const
{
return false;
}
NetEParam* NetEParam::dup_expr() const
{
return new NetEParam(des_, scope_, name_);
}
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid)
: expr_(exp), base_(base)
{
@@ -147,6 +171,13 @@ bool NetESelect::set_width(unsigned w)
/*
* $Log: net_expr.cc,v $
* Revision 1.8 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.7 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
* Revision 1.6 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+17 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.11 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
#endif
# include "config.h"
@@ -484,8 +484,24 @@ bool NexusSet::contains(const NexusSet&that) const
return true;
}
bool NexusSet::intersect(const NexusSet&that) const
{
for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) {
unsigned where = bsearch_(that[idx]);
if (where == nitems_)
continue;
if (items_[where] == that[idx])
return true;
}
return false;
}
/*
* $Log: net_link.cc,v $
* Revision 1.12 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.11 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
+8 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_output.cc,v 1.5 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.6 2002/09/17 04:39:20 steve Exp $"
#endif
# include "config.h"
@@ -42,8 +42,10 @@ void NetAssignBase::nex_output(NexusSet&out)
assert(lsig);
assert(lval_->more == 0);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
out.add(lsig->pin(idx).nexus());
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
unsigned off = lval_->get_loff() + idx;
out.add(lsig->pin(off).nexus());
}
}
@@ -85,6 +87,9 @@ void NetEvWait::nex_output(NexusSet&out)
/*
* $Log: net_nex_output.cc,v $
* Revision 1.6 2002/09/17 04:39:20 steve
* Account for part select in l-value.
*
* Revision 1.5 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+45 -11
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.19 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_scope.cc,v 1.20 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -78,33 +78,63 @@ NetScope::~NetScope()
free(module_name_);
}
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr)
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr,
NetExpr*msb, NetExpr*lsb, bool signed_flag)
{
NetExpr*&ref = parameters_[key];
NetExpr* res = ref;
ref = expr;
param_expr_t&ref = parameters_[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.msb = msb;
ref.lsb = lsb;
ref.signed_flag = signed_flag;
return res;
}
/*
* Return false if this creates a new parameter.
*/
bool NetScope::replace_parameter(const string&key, NetExpr*expr)
{
bool flag = true;
param_expr_t&ref = parameters_[key];
NetExpr* res = ref.expr;
if (res) {
delete res;
} else {
flag = false;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
}
ref.expr = expr;
return flag;
}
NetExpr* NetScope::set_localparam(const string&key, NetExpr*expr)
{
NetExpr*&ref = localparams_[key];
NetExpr* res = ref;
ref = expr;
param_expr_t&ref = localparams_[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
return res;
}
const NetExpr* NetScope::get_parameter(const string&key) const
{
map<string,NetExpr*>::const_iterator idx;
map<string,param_expr_t>::const_iterator idx;
idx = parameters_.find(key);
if (idx != parameters_.end())
return (*idx).second;
return (*idx).second.expr;
idx = localparams_.find(key);
if (idx != localparams_.end())
return (*idx).second;
return (*idx).second.expr;
return 0;
}
@@ -402,6 +432,10 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* Revision 1.20 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.19 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+31 -25
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.198 2002/08/19 00:06:12 steve Exp $"
#ident "$Id: netlist.cc,v 1.201 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -592,11 +592,21 @@ Link& NetFF::pin_Aset()
return pin(3);
}
const Link& NetFF::pin_Aset() const
{
return pin(3);
}
Link& NetFF::pin_Aclr()
{
return pin(4);
}
const Link& NetFF::pin_Aclr() const
{
return pin(4);
}
Link& NetFF::pin_Sload()
{
return pin(5);
@@ -640,6 +650,16 @@ const Link& NetFF::pin_Q(unsigned w) const
return pin(pn);
}
void NetFF::aset_value(const verinum&val)
{
aset_value_ = val;
}
const verinum& NetFF::aset_value() const
{
return aset_value_;
}
/*
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
@@ -2029,30 +2049,6 @@ NetEMemory* NetEMemory::dup_expr() const
assert(0);
}
NetEParam::NetEParam()
: des_(0)
{
}
NetEParam::NetEParam(Design*d, NetScope*s, const hname_t&n)
: des_(d), scope_(s), name_(n)
{
}
NetEParam::~NetEParam()
{
}
bool NetEParam::has_width() const
{
return false;
}
NetEParam* NetEParam::dup_expr() const
{
return new NetEParam(des_, scope_, name_);
}
NetEScope::NetEScope(NetScope*s)
: scope_(s)
{
@@ -2324,6 +2320,16 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.201 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.200 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.199 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
* Revision 1.198 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
+88 -6
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.260 2002/08/19 00:06:12 steve Exp $"
#ident "$Id: netlist.h,v 1.267 2002/10/23 01:47:17 steve Exp $"
#endif
/*
@@ -51,6 +51,7 @@ class NetProc;
class NetProcTop;
class NetRelease;
class NetScope;
class NetEvProbe;
class NetExpr;
class NetESignal;
class NetFuncDef;
@@ -296,6 +297,9 @@ class NexusSet {
// Return true if this set contains every nexus in that set.
bool contains(const NexusSet&that) const;
// Return true if this set contains any nexus in that set.
bool intersect(const NexusSet&that) const;
private:
Nexus**items_;
unsigned nitems_;
@@ -662,12 +666,20 @@ class NetFF : public NetNode {
const Link& pin_Clock() const;
const Link& pin_Enable() const;
const Link& pin_Aset() const;
const Link& pin_Aclr() const;
const Link& pin_Data(unsigned) const;
const Link& pin_Q(unsigned) const;
void aset_value(const verinum&val);
const verinum& aset_value() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
private:
verinum aset_value_;
};
@@ -1214,10 +1226,18 @@ class NetProc : public LineInfo {
// process. Most process types are not.
virtual bool is_asynchronous();
// Return true if this represents the root of a synchronous
// process. Most process types are not.
virtual bool is_synchronous();
// synthesize as asynchronous logic, and return true.
virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
private:
@@ -1400,6 +1420,10 @@ class NetBlock : public NetProc {
bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
// This version of emit_recurse scans all the statements of
// the begin-end block sequentially. It is typically of use
// for sequential blocks.
@@ -1530,6 +1554,10 @@ class NetCondit : public NetProc {
bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
@@ -1735,11 +1763,19 @@ class NetEvWait : public NetProc {
// process. This method checks.
virtual bool is_asynchronous();
// It is possible that this is the root of a synchronous
// process? This method checks.
virtual bool is_synchronous();
virtual void nex_output(NexusSet&out);
virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
private:
@@ -2116,13 +2152,20 @@ class NetProcTop : public LineInfo, public Attrib {
NetScope*scope();
const NetScope*scope() const;
/* Return true of this process represents combinational logic. */
/* Return true if this process represents combinational logic. */
bool is_asynchronous();
/* Create asynchronous logic from this thread and return true,
or return false if that cannot be done. */
bool synth_async(Design*des);
/* Return true if this process represents synchronous logic. */
bool is_synchronous();
/* Create synchronous logic from this thread and return true,
or return false if that cannot be done. */
bool synth_sync(Design*des);
void dump(ostream&, unsigned ind) const;
bool emit(struct target_t*tgt) const;
@@ -2157,8 +2200,9 @@ class NetProcTop : public LineInfo, public Attrib {
* n -- Logical inequality (!=)
* N -- Case inequality (!==)
* a -- Logical AND (&&)
* A -- Bitwise NAND (~&)
* o -- Logical OR (||)
* O -- Bit-wise NOR
* O -- Bit-wise NOR (~|)
* l -- Left shift (<<)
* r -- Right shift (>>)
* X -- Bitwise exclusive NOR (~^)
@@ -2733,10 +2777,17 @@ class NetScope {
the scope. The return value from set_parameter is the
previous expression, if there was one. */
NetExpr* set_parameter(const string&name, NetExpr*val);
NetExpr* set_parameter(const string&name, NetExpr*val,
NetExpr*msb, NetExpr*lsb, bool signed_flag);
NetExpr* set_localparam(const string&name, NetExpr*val);
const NetExpr*get_parameter(const string&name) const;
/* These are used by defparam elaboration to replace the
expression with a new expression, without affecting the
range or signed_flag. Return false if the name does not
exist. */
bool replace_parameter(const string&name, NetExpr*val);
/* These methods set or access events that live in this
scope. */
@@ -2837,8 +2888,14 @@ class NetScope {
signed char time_unit_, time_prec_;
map<string,NetExpr*>parameters_;
map<string,NetExpr*>localparams_;
struct param_expr_t {
NetExpr*expr;
NetExpr*msb;
NetExpr*lsb;
bool signed_flag;
};
map<string,param_expr_t>parameters_;
map<string,param_expr_t>localparams_;
NetEvent *events_;
NetNet *signals_;
@@ -3026,6 +3083,31 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.267 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.266 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.265 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.264 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.263 2002/09/26 01:13:14 steve
* Synthesize async set/reset is certain cases.
*
* Revision 1.262 2002/09/16 00:30:33 steve
* Add to synth2 support for synthesis of
* synchronous logic. This includes DFF enables
* modeled by if/then/else.
*
* Revision 1.261 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.260 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
+50 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.cc,v 1.3 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: netmisc.cc,v 1.4 2002/08/31 03:48:50 steve Exp $"
#endif
# include "config.h"
@@ -26,6 +26,52 @@
# include "netmisc.h"
# include "PExpr.h"
NetNet* add_to_net(Design*des, NetNet*sig, long val)
{
if (val == 0)
return sig;
NetScope*scope = sig->scope();
unsigned long abs_val = (val >= 0)? val : (-val);
unsigned width = sig->pin_count();
verinum val_v (abs_val, width);
NetConst*val_c = new NetConst(scope, scope->local_hsymbol(), val_v);
NetNet*val_s = new NetNet(scope, scope->local_hsymbol(),
NetNet::IMPLICIT, width);
val_s->local_flag(true);
NetNet*res = new NetNet(scope, scope->local_hsymbol(),
NetNet::IMPLICIT, width);
res->local_flag(true);
NetAddSub*add = new NetAddSub(scope, scope->local_hsymbol(), width);
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(sig->pin(idx), add->pin_DataA(idx));
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(val_c->pin(idx), add->pin_DataB(idx));
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(val_s->pin(idx), add->pin_DataB(idx));
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(res->pin(idx), add->pin_Result(idx));
if (val < 0)
add->attribute("LPM_Direction", verinum("SUB"));
else
add->attribute("LPM_Direction", verinum("ADD"));
des->add_node(add);
des->add_node(val_c);
return res;
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
{
@@ -44,6 +90,9 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/*
* $Log: netmisc.cc,v $
* Revision 1.4 2002/08/31 03:48:50 steve
* Fix reverse bit ordered bit select in continuous assignment.
*
* Revision 1.3 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+11 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.h,v 1.15 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: netmisc.h,v 1.16 2002/08/31 03:48:50 steve Exp $"
#endif
# include "netlist.h"
@@ -33,6 +33,13 @@
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
/*
* This function takes as input a NetNet signal and adds a constant
* value to it. If the val is 0, then simply return sig. Otherwise,
* return a new NetNet value that is the output of an addition.
*/
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
/*
* In some cases the lval is accessible as a pointer to the head of
* a list of NetAssign_ objects. This function returns the width of
@@ -50,6 +57,9 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
/*
* $Log: netmisc.h,v $
* Revision 1.16 2002/08/31 03:48:50 steve
* Fix reverse bit ordered bit select in continuous assignment.
*
* Revision 1.15 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+20 -5
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: parse.y,v 1.158 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: parse.y,v 1.162 2002/10/13 05:01:44 steve Exp $"
#endif
# include "config.h"
@@ -31,6 +31,7 @@ extern void lex_start_table();
extern void lex_end_table();
static svector<PExpr*>* active_range = 0;
static bool active_signed = false;
/*
* These are some common strength pairs that are used as defaults when
@@ -114,7 +115,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%token K_notif1 K_or K_output K_parameter K_pmos K_posedge K_primitive
%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime
%token K_reg K_release K_repeat
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalered
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalared
%token K_signed K_small K_specify
%token K_specparam K_strong0 K_strong1 K_supply0 K_supply1 K_table K_task
%token K_time K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand
@@ -735,6 +736,12 @@ expression
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NAND expression
{ PEBinary*tmp = new PEBinary('A', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NOR expression
{ PEBinary*tmp = new PEBinary('O', $1, $3);
tmp->set_file(@2.text);
@@ -888,7 +895,7 @@ expr_primary
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1
delete $1;
}
| identifier '[' expression ']'
{ PEIdent*tmp = new PEIdent(*$1);
@@ -1619,7 +1626,8 @@ parameter_assign
delete tmp;
tmp = 0;
} else {
pform_set_parameter($1, active_range, tmp);
pform_set_parameter($1, active_signed,
active_range, tmp);
}
delete $1;
}
@@ -1627,8 +1635,15 @@ parameter_assign
parameter_assign_decl
: parameter_assign_list
| range { active_range = $1; } parameter_assign_list
| range { active_range = $1; active_signed = false; }
parameter_assign_list
{ active_range = 0;
active_signed = false;
}
| K_signed range { active_range = $2; active_signed = true; }
parameter_assign_list
{ active_range = 0;
active_signed = false;
}
;
+7 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.101 2002/08/19 02:39:17 steve Exp $"
#ident "$Id: pform.cc,v 1.102 2002/09/01 03:01:48 steve Exp $"
#endif
# include "config.h"
@@ -1166,7 +1166,8 @@ void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r)
cur->set_memory_idx(l, r);
}
void pform_set_parameter(const string&name, svector<PExpr*>*range, PExpr*expr)
void pform_set_parameter(const string&name, bool signed_flag,
svector<PExpr*>*range, PExpr*expr)
{
assert(expr);
pform_cur_module->parameters[name].expr = expr;
@@ -1181,7 +1182,7 @@ void pform_set_parameter(const string&name, svector<PExpr*>*range, PExpr*expr)
pform_cur_module->parameters[name].msb = 0;
pform_cur_module->parameters[name].lsb = 0;
}
pform_cur_module->parameters[name].signed_flag = false;
pform_cur_module->parameters[name].signed_flag = signed_flag;
pform_cur_module->param_names.push_back(name);
}
@@ -1359,6 +1360,9 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* Revision 1.102 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
* Revision 1.101 2002/08/19 02:39:17 steve
* Support parameters with defined ranges.
*
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.63 2002/08/19 02:39:17 steve Exp $"
#ident "$Id: pform.h,v 1.64 2002/09/01 03:01:48 steve Exp $"
#endif
# include "netlist.h"
@@ -197,6 +197,7 @@ extern void pform_set_type_attrib(const string&name, const string&key,
char*value);
extern void pform_set_parameter(const string&name,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr);
extern void pform_set_localparam(const string&name, PExpr*expr);
@@ -258,6 +259,9 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.64 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
* Revision 1.63 2002/08/19 02:39:17 steve
* Support parameters with defined ranges.
*
+7 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.76 2002/08/19 02:39:17 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.77 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -712,6 +712,8 @@ void Module::dump(ostream&out) const
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << " parameter ";
if ((*cur).second.signed_flag)
out << "signed ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
@@ -846,6 +848,10 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.77 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.76 2002/08/19 02:39:17 steve
* Support parameters with defined ranges.
*
+81
View File
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sync.cc,v 1.3 2002/09/24 00:58:35 steve Exp $"
#endif
# include "config.h"
# include "functor.h"
# include "netlist.h"
# include <assert.h>
/*
* Most process statements are not roots of synchronous logic.
*/
bool NetProc::is_synchronous()
{
return false;
}
bool NetEvWait::is_synchronous()
{
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
NetEvent*ev = events_[idx];
if (ev->nprobe() == 0)
return false;
for (unsigned pdx = 0 ; pdx < ev->nprobe() ; pdx += 1) {
NetEvProbe*pr = ev->probe(pdx);
/* No level sensitive clocks. */
if (pr->edge() == NetEvProbe::ANYEDGE)
return false;
}
}
/* So we know that there is a clock source. Check that the
input to the storage is asynchronous. */
return true; //statement_->is_asynchronous();
}
bool NetProcTop::is_synchronous()
{
if (type_ == NetProcTop::KINITIAL)
return false;
return statement_->is_synchronous();
}
/*
* $Log: sync.cc,v $
* Revision 1.3 2002/09/24 00:58:35 steve
* More detailed check of process edge events.
*
* Revision 1.2 2002/09/16 21:55:06 steve
* Reject multiple probes on synchronous logic.
*
* Revision 1.1 2002/09/16 00:30:33 steve
* Add to synth2 support for synthesis of
* synchronous logic. This includes DFF enables
* modeled by if/then/else.
*
*/
+411 -16
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.8 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: synth2.cc,v 1.17 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -27,6 +27,26 @@
# include "compiler.h"
# include <assert.h>
bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
{
return false;
}
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events)
{
if (events.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
des->errors += 1;
}
/* Synthesize the input to the DFF. */
return synth_async(des, scope, nex_map, nex_out);
}
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
{
unsigned idx = 0;
@@ -57,11 +77,12 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
assert(lsig);
assert(lval_->more == 0);
assert(lsig->pin_count() == nex_map->pin_count());
assert(lval_->lwidth() == nex_map->pin_count());
assert(nex_map->pin_count() <= rsig->pin_count());
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus());
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
unsigned off = lval_->get_loff()+idx;
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
connect(nex_out->pin(ptr), rsig->pin(idx));
}
@@ -85,27 +106,33 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
do {
cur = cur->next_;
/* Create a temporary nex_out for the substatement. */
/* Create a temporary nex_map for the substatement. */
NexusSet tmp_set;
cur->nex_output(tmp_set);
NetNet*tmp_out = new NetNet(scope, "tmp", NetNet::WIRE,
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_out->pin(idx));
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_map->pin(idx));
bool ok_flag = cur->synth_async(des, scope, tmp_out, tmp_out);
/* Create also a temporary net_out to collect the
output. */
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
tmp_set.count());
bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out);
flag = flag && ok_flag;
if (ok_flag == false)
continue;
/* Use tne nex_map to link up the output from the
/* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(nex_out->pin(ptr), tmp_out->pin(idx));
}
delete tmp_map;
delete tmp_out;
} while (cur != last_);
@@ -201,6 +228,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
NetNet*ssig = expr_->synthesize(des);
assert(ssig);
if (if_ == 0)
return false;
if (else_ == 0) {
cerr << get_line() << ": error: Asynchronous if statement"
<< " is missing the else clause." << endl;
return false;
}
assert(if_ != 0);
assert(else_ != 0);
@@ -241,12 +276,6 @@ bool NetEvWait::synth_async(Design*des, NetScope*scope,
return statement_->synth_async(des, scope, nex_map, nex_out);
}
bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
{
return false;
}
bool NetProcTop::synth_async(Design*des)
{
NexusSet nex_set;
@@ -263,6 +292,330 @@ bool NetProcTop::synth_async(Design*des)
return flag;
}
/*
* This method is called when a block is encountered near the surface
* of a synchronous always statement. For example, this code will be
* invoked for input like this:
*
* always @(posedge clk...) begin
* <statement1>
* <statement2>
* ...
* end
*
* This needs to be split into a DFF bank for each statement, because
* the statements may each infer different reset and enable signals.
*/
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events_in)
{
if (last_ == 0)
return true;
bool flag = true;
NetProc*cur = last_;
unsigned offset = 0;
do {
cur = cur->next_;
/* Create a temporary nex_map for the substatement. */
NexusSet tmp_set;
cur->nex_output(tmp_set);
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_map->pin(idx));
/* Create also a temporary net_out to collect the
output. */
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
tmp_set.count());
verinum tmp_aset = ff->aset_value();
/* Create a new DFF to handle this part of the begin-end
block. Connect this NetFF to the associated pins of
the existing wide NetFF device. While I'm at it, also
copy the aset_value bits for the new ff device. */
NetFF*ff2 = new NetFF(scope, scope->local_hsymbol().c_str(),
tmp_out->pin_count());
des->add_node(ff2);
verinum aset_value2 (verinum::V1, ff2->width());
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(ff->pin_Data(ptr), ff2->pin_Data(idx));
connect(ff->pin_Q(ptr), ff2->pin_Q(idx));
if (ptr < tmp_aset.len())
aset_value2.set(idx, tmp_aset[ptr]);
}
if (ff->pin_Aclr().is_linked())
connect(ff->pin_Aclr(), ff2->pin_Aclr());
if (ff->pin_Aset().is_linked())
connect(ff->pin_Aset(), ff2->pin_Aset());
if (ff->pin_Clock().is_linked())
connect(ff->pin_Clock(), ff2->pin_Clock());
if (ff->pin_Enable().is_linked())
connect(ff->pin_Enable(),ff2->pin_Enable());
/* Remember to store the aset value into the new FF. If
this leads to an Aset value of 0 (and Aclr is not
otherwise used) then move the Aset input to Aclr. */
if (tmp_aset.len() == ff->width()) {
if ((aset_value2.as_ulong() == 0)
&& ff2->pin_Aset().is_linked()
&& !ff2->pin_Aclr().is_linked()) {
connect(ff2->pin_Aclr(), ff2->pin_Aset());
ff2->pin_Aset().unlink();
} else {
ff2->aset_value(aset_value2);
}
}
/* Now go on with the synchronous synthesis for this
subset of the statement. */
bool ok_flag = cur->synth_sync(des, scope, ff2, tmp_map,
tmp_out, events_in);
flag = flag && ok_flag;
if (ok_flag == false)
continue;
/* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(nex_out->pin(ptr), tmp_out->pin(idx));
}
delete tmp_map;
delete tmp_out;
offset += ff2->width();
} while (cur != last_);
/* Done. The large NetFF is no longer needed, as it has been
taken up by the smaller NetFF devices. */
assert(offset == ff->width());
delete ff;
return flag;
}
/*
* This method handles the case where I find a conditional near the
* surface of a synchronous thread. This conditional can be a CE or an
* asynchronous set/reset, depending on whether the pin of the
* expression is connected to an event, or not.
*/
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events_in)
{
/* Synthesize the enable expression. */
NetNet*ce = expr_->synthesize(des);
assert(ce->pin_count() == 1);
/* Try first to turn the ce into an asynchronous set/reset
input. If the ce is linked to a probe, then that probe is a
set/reset input. */
for (unsigned idx = 0 ; idx < events_in.count() ; idx += 1) {
NetEvProbe*ev = events_in[idx];
if (connected(ce->pin(0), ev->pin(0))) {
assert(ev->edge() == NetEvProbe::POSEDGE);
/* Synthesize the true clause to figure out what
kind of set/reset we have. */
NetNet*asig = new NetNet(scope, scope->local_hsymbol(),
NetNet::WIRE, nex_map->pin_count());
asig->local_flag(true);
if_->synth_async(des, scope, nex_map, asig);
assert(asig->pin_count() == ff->width());
/* Collect the set/reset value into a verinum. If
this turns out to be entirely 0 values, then
use the Aclr input. Otherwise, use the Aset
input and save the set value. */
verinum tmp (verinum::V0, ff->width());
for (unsigned bit = 0 ; bit < ff->width() ; bit += 1) {
assert(asig->pin(bit).nexus()->drivers_constant());
tmp.set(bit, asig->pin(bit).nexus()->driven_value());
}
assert(tmp.is_defined());
if (tmp.as_ulong() == 0) {
connect(ff->pin_Aclr(), ce->pin(0));
} else {
connect(ff->pin_Aset(), ce->pin(0));
ff->aset_value(tmp);
}
delete asig;
assert(events_in.count() == 1);
return else_->synth_sync(des, scope, ff, nex_map,
nex_out, svector<NetEvProbe*>(0));
}
}
/* Failed to find an asynchronous set/reset, so any events
input are probably in error. */
if (events_in.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
des->errors += 1;
}
/* If this is an if/then/else, then it is likely a
combinational if, and I should synthesize it that way. */
if (if_ && else_) {
return synth_async(des, scope, nex_map, nex_out);
}
assert(if_);
assert(!else_);
/* Synthesize the input to the DFF. */
bool flag = if_->synth_async(des, scope, nex_map, nex_out);
if (flag == false)
return flag;
assert(expr_);
connect(ff->pin_Enable(), ce->pin(0));
return true;
}
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events_in)
{
if (events_in.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
des->errors += 1;
}
assert(events_in.count() == 0);
/* This can't be other then one unless there are named events,
which I cannot synthesize. */
assert(nevents_ == 1);
NetEvent*ev = events_[0];
assert(ev->nprobe() >= 1);
svector<NetEvProbe*>events (ev->nprobe() - 1);
/* Get the input set from the substatement. This will be used
to figure out which of the probes in the clock. */
NexusSet*statement_input = statement_ -> nex_input();
/* Search for a clock input. The clock input is the edge event
that is not also an input to the substatement. */
NetEvProbe*pclk = 0;
unsigned event_idx = 0;
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
NetEvProbe*tmp = ev->probe(idx);
assert(tmp->pin_count() == 1);
NexusSet tmp_nex;
tmp_nex .add( tmp->pin(0).nexus() );
if (! statement_input ->contains(tmp_nex)) {
if (pclk != 0) {
cerr << get_line() << ": error: Too many "
<< "clocks for synchronous logic." << endl;
cerr << get_line() << ": : Perhaps an"
<< " asynchronous set/reset is misused?" << endl;
des->errors += 1;
}
pclk = tmp;
} else {
events[event_idx++] = tmp;
}
}
if (pclk == 0) {
cerr << get_line() << ": error: None of the edges"
<< " are valid clock inputs." << endl;
cerr << get_line() << ": : Perhaps the clock"
<< " is read by a statement or expression?" << endl;
return false;
}
connect(ff->pin_Clock(), pclk->pin(0));
if (pclk->edge() == NetEvProbe::NEGEDGE)
ff->attribute("Clock:LPM_Polarity", verinum("INVERT"));
#if 0
if (ev->nprobe() > 1) {
cerr << get_line() << ": sorry: I don't know how "
<< "to synthesize asynchronous DFF controls."
<< endl;
return false;
}
#endif
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope, ff,
nex_map, nex_out, events);
return flag;
}
bool NetProcTop::synth_sync(Design*des)
{
NexusSet nex_set;
statement_->nex_output(nex_set);
NetFF*ff = new NetFF(scope(), scope()->local_hsymbol().c_str(),
nex_set.count());
des->add_node(ff);
ff->attribute("LPM_FFType", verinum("DFF"));
/* The D inputs to the DFF device will receive the output from
the statments of the process. */
NetNet*nex_d = new NetNet(scope(), scope()->local_hsymbol().c_str(),
NetNet::WIRE, nex_set.count());
nex_d->local_flag(true);
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_d->pin(idx), ff->pin_Data(idx));
}
/* The Q outputs of the DFF will connect to the actual outputs
of the process. Thus, the DFF will be between the outputs
of the process and the outputs of the substatement. */
NetNet*nex_q = new NetNet(scope(), "tmpq", NetNet::WIRE,
nex_set.count());
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_set[idx], nex_q->pin(idx));
connect(nex_q->pin(idx), ff->pin_Q(idx));
}
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope(), ff,
nex_q, nex_d,
svector<NetEvProbe*>());
delete nex_q;
return flag;
}
class synth2_f : public functor_t {
public:
@@ -281,6 +634,18 @@ void synth2_f::process(class Design*des, class NetProcTop*top)
if (top->attribute("ivl_synthesis_off").as_ulong() != 0)
return;
if (top->is_synchronous()) do {
bool flag = top->synth_sync(des);
if (! flag) {
cerr << top->get_line() << ": error: "
<< "Unable to synthesize synchronous process." << endl;
des->errors += 1;
return;
}
des->delete_process(top);
return;
} while (0);
if (! top->is_asynchronous()) {
bool synth_error_flag = false;
if (top->attribute("ivl_combinational").as_ulong() != 0) {
@@ -324,6 +689,36 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.17 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.16 2002/10/21 01:42:09 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.15 2002/10/20 19:19:37 steve
* Handle conditional error cases better.
*
* Revision 1.14 2002/09/26 03:42:10 steve
* Remove excess debug messages.
*
* Revision 1.13 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.12 2002/09/26 01:13:14 steve
* Synthesize async set/reset is certain cases.
*
* Revision 1.11 2002/09/24 00:58:35 steve
* More detailed check of process edge events.
*
* Revision 1.10 2002/09/17 04:40:28 steve
* Connect output of block to net_out, instead of statement outputs.
*
* Revision 1.9 2002/09/16 00:30:33 steve
* Add to synth2 support for synthesis of
* synchronous logic. This includes DFF enables
* modeled by if/then/else.
*
* Revision 1.8 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
+43 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.86 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.88 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -540,6 +540,29 @@ extern "C" const char* ivl_lpm_basename(ivl_lpm_t net)
return basename(net->scope, net->name);
}
extern "C" ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net)
{
assert(net);
switch(net->type) {
case IVL_LPM_FF:
return net->u_.ff.aclr;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net)
{
assert(net);
switch(net->type) {
case IVL_LPM_FF:
return net->u_.ff.aset;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
{
@@ -554,6 +577,18 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
}
}
extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.aset_value;
default:
assert(0);
return 0;
}
}
extern "C" ivl_scope_t ivl_lpm_define(ivl_lpm_t net)
{
assert(net);
@@ -1550,6 +1585,13 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.88 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.87 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.86 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+37 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-expr.cc,v 1.28 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.29 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -103,6 +103,38 @@ void dll_target::mul_expr_by_const_(long val)
expr_ = tmps;
}
ivl_expr_t dll_target::expr_from_value_(const verinum&val)
{
ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr);
unsigned idx;
char*bits;
expr->type_ = IVL_EX_NUMBER;
expr->width_= val.len();
expr->signed_ = val.has_sign()? 1 : 0;
expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_);
for (idx = 0 ; idx < expr->width_ ; idx += 1)
switch (val.get(idx)) {
case verinum::V0:
bits[idx] = '0';
break;
case verinum::V1:
bits[idx] = '1';
break;
case verinum::Vx:
bits[idx] = 'x';
break;
case verinum::Vz:
bits[idx] = 'z';
break;
default:
assert(0);
}
return expr;
}
void dll_target::expr_binary(const NetEBinary*net)
{
assert(expr_ == 0);
@@ -458,6 +490,10 @@ void dll_target::expr_unary(const NetEUnary*net)
/*
* $Log: t-dll-expr.cc,v $
* Revision 1.29 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.28 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+33 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.95 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: t-dll.cc,v 1.97 2002/10/23 01:47:18 steve Exp $"
#endif
# include "config.h"
@@ -1361,6 +1361,31 @@ void dll_target::lpm_ff(const NetFF*net)
obj->u_.ff.we = 0;
}
if (net->pin_Aclr().is_linked()) {
nex = net->pin_Aclr().nexus();
assert(nex->t_cookie());
obj->u_.ff.aclr = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.aclr);
nexus_lpm_add(obj->u_.ff.aclr, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
} else {
obj->u_.ff.aclr = 0;
}
if (net->pin_Aset().is_linked()) {
nex = net->pin_Aset().nexus();
assert(nex->t_cookie());
obj->u_.ff.aset = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.aset);
nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
verinum tmp = net->aset_value();
obj->u_.ff.aset_value = expr_from_value_(tmp);
} else {
obj->u_.ff.aset = 0;
obj->u_.ff.aset_value = 0;
}
if (obj->u_.ff.width == 1) {
nex = net->pin_Q(0).nexus();
assert(nex->t_cookie());
@@ -1954,6 +1979,13 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.97 2002/10/23 01:47:18 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.96 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.95 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+13 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.93 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: t-dll.h,v 1.95 2002/10/23 01:47:17 steve Exp $"
#endif
# include "target.h"
@@ -154,6 +154,8 @@ struct dll_target : public target_t, public expr_scan_t {
void sub_off_from_expr_(long);
void mul_expr_by_const_(long);
static ivl_expr_t expr_from_value_(const verinum&that);
};
/*
@@ -267,6 +269,8 @@ struct ivl_lpm_s {
unsigned short swid; // ram only
ivl_nexus_t clk;
ivl_nexus_t we;
ivl_nexus_t aclr;
ivl_nexus_t aset;
union {
ivl_nexus_t*pins;
ivl_nexus_t pin;
@@ -280,6 +284,7 @@ struct ivl_lpm_s {
ivl_nexus_t pin;
} s;
ivl_memory_t mem; // ram only
ivl_expr_t aset_value;
} ff;
struct ivl_lpm_mux_s {
@@ -617,6 +622,13 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* Revision 1.95 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.94 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.93 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+10 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-generic-edif.c,v 1.9 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: d-generic-edif.c,v 1.10 2002/10/28 02:05:56 steve Exp $"
#endif
# include "device.h"
@@ -394,12 +394,20 @@ const struct device_s d_generic_edif = {
0,
0,
0,
0
0,
0, /* show_add */
0, /* show_sub */
0, /* show_shiftl */
0 /* show_shiftr */
};
/*
* $Log: d-generic-edif.c,v $
* Revision 1.10 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.9 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+10 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-generic.c,v 1.11 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: d-generic.c,v 1.12 2002/10/28 02:05:56 steve Exp $"
#endif
# include "device.h"
@@ -503,13 +503,21 @@ const struct device_s d_generic = {
generic_show_dff,
generic_show_cmp_eq,
generic_show_cmp_eq,
0, /* ge not implemented */
generic_show_mux,
generic_show_add
generic_show_add,
0, /* subtract not implemented */
0,
0
};
/*
* $Log: d-generic.c,v $
* Revision 1.12 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.11 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+559 -43
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-virtex.c,v 1.13 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: d-virtex.c,v 1.16 2002/10/28 02:05:56 steve Exp $"
#endif
# include "device.h"
@@ -54,6 +54,9 @@
*
* MUXCY_L LO, S, DI, CI
*
* MUXF5 O, S, I0, I1
* MUXF6 O, S, I0, I1
*
* XORCY O, LI, CI
*/
@@ -137,9 +140,25 @@ static const char*virtex_library_text =
" (viewType NETLIST)\n"
" (interface\n"
" (port LO (direction OUTPUT))\n"
" (port S (direction INPUT))\n"
" (port S (direction INPUT))\n"
" (port DI (direction INPUT))\n"
" (port CI (direction INPUT)))))\n"
" (cell MUXF5 (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
" (interface\n"
" (port O (direction OUTPUT))\n"
" (port S (direction INPUT))\n"
" (port I0 (direction INPUT))\n"
" (port I1 (direction INPUT)))))\n"
" (cell MUXF6 (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
" (interface\n"
" (port O (direction OUTPUT))\n"
" (port S (direction INPUT))\n"
" (port I0 (direction INPUT))\n"
" (port I1 (direction INPUT)))))\n"
" (cell OBUF (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
@@ -900,7 +919,7 @@ static void edif_show_virtex_eq(ivl_lpm_t net)
* of the mux are themselves LUT devices and generate MUXF5 devices in
* those cases. This currently does *not* do that.
*/
static void edif_show_virtex_mux(ivl_lpm_t net)
static void edif_show_virtex_muxs1(ivl_lpm_t net)
{
unsigned idx;
assert(ivl_lpm_width(net) >= 1);
@@ -921,11 +940,237 @@ static void edif_show_virtex_mux(ivl_lpm_t net)
}
}
/*
* This supports the general mux with two select inputs. This is a 4:1
* mux. Use two LUT3 devices and a MUXF5 to form each bit slice of the
* full mux. By using a MUXF5, we pretty much confine the bit slice to
* a Virtex CLB slice.
*/
static void edif_show_virtex_muxs2(ivl_lpm_t net)
{
unsigned idx;
assert(ivl_lpm_width(net) >= 1);
assert(ivl_lpm_selects(net) == 2);
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
char tmp_name[1024];
edif_uref += 1;
sprintf(tmp_name, "%s<%u>", ivl_lpm_name(net), idx);
fprintf(xnf, "(instance U%uA"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n", edif_uref);
fprintf(xnf, "(instance U%uB"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n", edif_uref);
fprintf(xnf, "(instance (rename U%uF \"%s\")"
" (viewRef net"
" (cellRef MUXF5 (libraryRef VIRTEX))))\n",
edif_uref, tmp_name);
fprintf(xnf, "(net U%uAF (joined"
" (portRef O (instanceRef U%uA))"
" (portRef I0 (instanceRef U%uF))))\n",
edif_uref, edif_uref, edif_uref);
fprintf(xnf, "(net U%uBF (joined"
" (portRef O (instanceRef U%uB))"
" (portRef I1 (instanceRef U%uF))))\n",
edif_uref, edif_uref, edif_uref);
sprintf(tmp_name, "(portRef I0 (instanceRef U%uA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 0, idx), tmp_name);
sprintf(tmp_name, "(portRef I1 (instanceRef U%uA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 1, idx), tmp_name);
sprintf(tmp_name, "(portRef I0 (instanceRef U%uB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 2, idx), tmp_name);
sprintf(tmp_name, "(portRef I1 (instanceRef U%uB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 3, idx), tmp_name);
sprintf(tmp_name, "(portRef I2 (instanceRef U%uA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 0), tmp_name);
sprintf(tmp_name, "(portRef I2 (instanceRef U%uB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 0), tmp_name);
sprintf(tmp_name, "(portRef S (instanceRef U%uF))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 1), tmp_name);
sprintf(tmp_name, "(portRef O (instanceRef U%uF))", edif_uref);
edif_set_nexus_joint(ivl_lpm_q(net, idx), tmp_name);
}
}
static void edif_show_virtex_muxs3(ivl_lpm_t net)
{
unsigned idx;
assert(ivl_lpm_width(net) >= 1);
assert(ivl_lpm_selects(net) == 3);
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
char tmp_name[1024];
edif_uref += 1;
sprintf(tmp_name, "%s<%u>", ivl_lpm_name(net), idx);
fprintf(xnf, "(instance U%uAA"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n", edif_uref);
fprintf(xnf, "(instance U%uBA"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n", edif_uref);
fprintf(xnf, "(instance U%uFA"
" (viewRef net"
" (cellRef MUXF5 (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%uAFA (joined"
" (portRef O (instanceRef U%uAA))"
" (portRef I0 (instanceRef U%uFA))))\n",
edif_uref, edif_uref, edif_uref);
fprintf(xnf, "(net U%uBFA (joined"
" (portRef O (instanceRef U%uBA))"
" (portRef I1 (instanceRef U%uFA))))\n",
edif_uref, edif_uref, edif_uref);
fprintf(xnf, "(instance U%uAB"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n", edif_uref);
fprintf(xnf, "(instance U%uBB"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n", edif_uref);
fprintf(xnf, "(instance U%uFB"
" (viewRef net"
" (cellRef MUXF5 (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%uAFB (joined"
" (portRef O (instanceRef U%uAB))"
" (portRef I0 (instanceRef U%uFB))))\n",
edif_uref, edif_uref, edif_uref);
fprintf(xnf, "(net U%uBFB (joined"
" (portRef O (instanceRef U%uBB))"
" (portRef I1 (instanceRef U%uFB))))\n",
edif_uref, edif_uref, edif_uref);
/* Connect the two MUXF5 devices to the MUXF6. */
fprintf(xnf, "(instance (rename U%uF \"%s\")"
" (viewRef net"
" (cellRef MUXF6 (libraryRef VIRTEX))))\n",
edif_uref, tmp_name);
fprintf(xnf, "(net U%uFA (joined"
" (portRef O (instanceRef U%uFA))"
" (portRef I0 (instanceRef U%uF))))\n",
edif_uref, edif_uref, edif_uref);
fprintf(xnf, "(net U%uFB (joined"
" (portRef O (instanceRef U%uFB))"
" (portRef I1 (instanceRef U%uF))))\n",
edif_uref, edif_uref, edif_uref);
sprintf(tmp_name, "(portRef I0 (instanceRef U%uAA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 0, idx), tmp_name);
sprintf(tmp_name, "(portRef I1 (instanceRef U%uAA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 1, idx), tmp_name);
sprintf(tmp_name, "(portRef I0 (instanceRef U%uBA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 2, idx), tmp_name);
sprintf(tmp_name, "(portRef I1 (instanceRef U%uBA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 3, idx), tmp_name);
sprintf(tmp_name, "(portRef I0 (instanceRef U%uAB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 4, idx), tmp_name);
sprintf(tmp_name, "(portRef I1 (instanceRef U%uAB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 5, idx), tmp_name);
sprintf(tmp_name, "(portRef I0 (instanceRef U%uBB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 6, idx), tmp_name);
sprintf(tmp_name, "(portRef I1 (instanceRef U%uBB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data2(net, 7, idx), tmp_name);
sprintf(tmp_name, "(portRef I2 (instanceRef U%uAA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 0), tmp_name);
sprintf(tmp_name, "(portRef I2 (instanceRef U%uBA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 0), tmp_name);
sprintf(tmp_name, "(portRef I2 (instanceRef U%uAB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 0), tmp_name);
sprintf(tmp_name, "(portRef I2 (instanceRef U%uBB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 0), tmp_name);
sprintf(tmp_name, "(portRef S (instanceRef U%uFA))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 1), tmp_name);
sprintf(tmp_name, "(portRef S (instanceRef U%uFB))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 1), tmp_name);
sprintf(tmp_name, "(portRef S (instanceRef U%uF))", edif_uref);
edif_set_nexus_joint(ivl_lpm_select(net, 2), tmp_name);
sprintf(tmp_name, "(portRef O (instanceRef U%uF))", edif_uref);
edif_set_nexus_joint(ivl_lpm_q(net, idx), tmp_name);
}
}
static void edif_show_virtex_mux(ivl_lpm_t net)
{
switch (ivl_lpm_selects(net)) {
case 1:
edif_show_virtex_muxs1(net);
break;
case 2:
edif_show_virtex_muxs2(net);
break;
case 3:
edif_show_virtex_muxs3(net);
break;
default:
assert(0);
break;
}
}
static void edif_show_virtex_add(ivl_lpm_t net)
{
char jbuf [1024];
unsigned idx;
unsigned nref = 0;
unsigned ha_init = 6;
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
ha_init = 6;
break;
case IVL_LPM_SUB:
ha_init = 9;
break;
default:
assert(0);
}
/* Handle the special case that the adder is only one bit
wide. Generate an XOR gate to perform the half-add. */
@@ -936,7 +1181,7 @@ static void edif_show_virtex_add(ivl_lpm_t net)
ivl_lpm_q(net, 0),
ivl_lpm_data(net, 0),
ivl_lpm_datab(net, 0),
"6");
(ha_init == 6) ? "6" : "9");
return;
}
@@ -947,8 +1192,8 @@ static void edif_show_virtex_add(ivl_lpm_t net)
includes the LUT2 device to perform the addition, and a
MUXCY_L device to send the carry up to the next bit. */
fprintf(xnf, "(instance (rename U%u_L0 \"%s\"[0])"
" (property INIT (string \"6\"))", edif_uref,
ivl_lpm_name(net));
" (property INIT (string \"%u\"))", edif_uref,
ivl_lpm_name(net), ha_init);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
@@ -974,8 +1219,8 @@ static void edif_show_virtex_add(ivl_lpm_t net)
device, the other devices have local names. */
for (idx = 1 ; idx < (ivl_lpm_width(net)-1) ; idx += 1) {
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"6\"))",
edif_uref, idx);
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"%u\"))",
edif_uref, idx, ha_init);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
@@ -1016,8 +1261,8 @@ static void edif_show_virtex_add(ivl_lpm_t net)
}
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"6\"))",
edif_uref, idx);
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"%u\"))",
edif_uref, idx, ha_init);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
@@ -1049,6 +1294,295 @@ static void edif_show_virtex_add(ivl_lpm_t net)
edif_set_nexus_joint(ivl_lpm_q(net, idx), jbuf);
}
static void virtex_show_cmp_ge(ivl_lpm_t net)
{
char jbuf [1024];
unsigned idx;
unsigned nref = 0;
/* Handle the special case that the adder is only one bit
wide. Generate an XOR gate to perform the half-add. */
if (ivl_lpm_width(net) == 1) {
edif_uref += 1;
edif_show_lut2(ivl_lpm_name(net), edif_uref,
ivl_lpm_q(net, 0),
ivl_lpm_data(net, 0),
ivl_lpm_datab(net, 0),
"D");
return;
}
assert(ivl_lpm_width(net) > 1);
edif_uref += 1;
/* First, draw the bottom bit slice of the comparator. This
includes the LUT2 device to perform the addition, and a
MUXCY_L device to send the carry up to the next bit. */
fprintf(xnf, "(instance (rename U%u_L0 \"%s\"[0])"
" (property INIT (string \"9\"))", edif_uref,
ivl_lpm_name(net));
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance U%u_M0", edif_uref);
fprintf(xnf, " (viewRef net"
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data(net, 0), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L0))", edif_uref);
edif_set_nexus_joint(ivl_lpm_datab(net, 0), jbuf);
sprintf(jbuf, "(portRef DI (instanceRef U%u_M0))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data(net, 0), jbuf);
switch (ivl_lpm_type(net)) {
case IVL_LPM_CMP_GT:
fprintf(xnf, "(instance U%u_FILL "
" (viewRef net"
" (cellRef GND (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%u_FILLN (joined"
" (portRef GROUND (instanceRef U%u_FILL))"
" (portRef CI (instanceRef U%u_M0))))\n",
edif_uref, edif_uref, edif_uref);
break;
case IVL_LPM_CMP_GE:
fprintf(xnf, "(instance U%u_FILL "
" (viewRef net"
" (cellRef VCC (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%u_FILLN (joined"
" (portRef VCC (instanceRef U%u_FILL))"
" (portRef CI (instanceRef U%u_M0))))\n",
edif_uref, edif_uref, edif_uref);
break;
default:
assert(0);
}
/* Now draw all the inside bit slices. These include the LUT2
device for the basic add, the MUXCY_L device to propagate
the carry, and an XORCY device to generate the real
output. The XORCY device carries the name of the LPM
device, the other devices have local names. */
for (idx = 1 ; idx < (ivl_lpm_width(net)-1) ; idx += 1) {
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"9\"))",
edif_uref, idx);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance U%u_M%u", edif_uref, idx);
fprintf(xnf, " (viewRef net"
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
fprintf(xnf, "(net U%uN%u (joined"
" (portRef O (instanceRef U%u_L%u))"
" (portRef S (instanceRef U%u_M%u))))\n",
edif_uref, nref++, edif_uref, idx, edif_uref, idx);
fprintf(xnf, "(net U%uN%u (joined"
" (portRef CI (instanceRef U%u_M%u))"
" (portRef LO (instanceRef U%u_M%u))))\n",
edif_uref, nref++, edif_uref, idx, edif_uref, idx-1);
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_datab(net, idx), jbuf);
sprintf(jbuf, "(portRef DI (instanceRef U%u_M%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
}
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"9\"))",
edif_uref, idx);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(net U%uN%u (joined"
" (portRef O (instanceRef U%u_L%u))"
" (portRef LI (instanceRef U%u_X%u))))\n",
edif_uref, nref++, edif_uref, idx, edif_uref, idx);
fprintf(xnf, "(net U%uN%u (joined"
" (portRef CI (instanceRef U%u_X%u))"
" (portRef LO (instanceRef U%u_M%u))))\n",
edif_uref, nref++, edif_uref, idx, edif_uref, idx-1);
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_datab(net, idx), jbuf);
sprintf(jbuf, "(portRef DI (instanceRef U%u_M%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
sprintf(jbuf, "(portRef LO (instanceRef U%u_M%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_q(net, 0), jbuf);
}
/*
* The left shift is implemented as a matrix of MUX2_1 devices. The
* matrix has as many rows as the device width, and a column for each
* select.
*/
static void virtex_show_shiftl(ivl_lpm_t net)
{
char jbuf[64];
unsigned width = ivl_lpm_width(net);
unsigned nsel = 0, swid = 0;
unsigned sdx, qdx;
edif_uref += 1;
/* First, find out how many select inputs we really need. We
can only use the selects that are enough to shift out the
entire width of the device. The excess can be used as an
enable for the last column. When disabled, the last column
emits zeros. */
while (nsel < ivl_lpm_selects(net)) {
nsel += 1;
swid = 1 << nsel;
if (swid >= width)
break;
}
assert(nsel > 0);
/* Draw the gates of the matrix, and connect the select inputs
up the columns. Column 0 is the first to see the input
data, so it gets select[0], and so on. */
for (sdx = 0 ; sdx < nsel ; sdx += 1) {
unsigned lutn = 3;
if ( (sdx == (nsel-1)) && (nsel < ivl_lpm_selects(net)))
lutn = 4;
for (qdx = 0 ; qdx < width ; qdx += 1) {
fprintf(xnf, "(instance U%uC%uR%u"
" (viewRef net"
" (cellRef LUT%u (libraryRef VIRTEX)))"
" (property INIT (string \"CA\")))\n",
edif_uref, sdx, qdx, lutn);
sprintf(jbuf, "(portRef I2 (instanceRef U%uC%uR%u))",
edif_uref, sdx, qdx);
edif_set_nexus_joint(ivl_lpm_select(net, sdx), jbuf);
/* If this is the last column, and there are
excess selects to account for, then connect the
I3 inputs of the LUT4 devices to the excess
select, to act as an enable. */
if (lutn == 4) {
assert((nsel + 1) == ivl_lpm_selects(net));
sprintf(jbuf, "(portRef I3 (instanceRef U%uC%uR%u))",
edif_uref, sdx, qdx);
edif_set_nexus_joint(ivl_lpm_select(net, nsel), jbuf);
}
}
}
/* Connect the output of the matrix to the outputs of the
shiftl. */
for (qdx = 0 ; qdx < width ; qdx += 1) {
sprintf(jbuf, "(portRef O (instanceRef U%uC%uR%u))",
edif_uref, nsel-1, qdx);
edif_set_nexus_joint(ivl_lpm_q(net, qdx), jbuf);
}
/* Connect the input of the matrix to the inputs of the
shiftl. The B inputs of the input column MUXes also get the
inputs shifted up 1. */
for (qdx = 0 ; qdx < width ; qdx += 1) {
sprintf(jbuf, "(portRef I0 (instanceRef U%uC%uR%u))",
edif_uref, 0, qdx);
edif_set_nexus_joint(ivl_lpm_data(net, qdx), jbuf);
if (qdx < (width-1)) {
sprintf(jbuf, "(portRef I1 (instanceRef U%uC%uR%u))",
edif_uref, 0, qdx+1);
edif_set_nexus_joint(ivl_lpm_data(net, qdx), jbuf);
}
}
/* Connect the B side 0 padding to the input column. */
fprintf(xnf, "(instance U%uC%uP"
" (viewRef net"
" (cellRef GND (libraryRef VIRTEX))))\n",
edif_uref, 0);
fprintf(xnf, "(net U%uC0PN (joined"
" (portRef I1 (instanceRef U%uC0R0))"
" (portRef GROUND (instanceRef U%uC0P))))\n",
edif_uref, edif_uref, edif_uref);
/* Connect the sdx column outputs to the sdx+1 column
inputs. This includes the A side which is straight
through, and the B side which is shifted based on the
selector identity. */
for (sdx = 0 ; sdx < (nsel-1) ; sdx += 1) {
unsigned shift = 1 << sdx;
for (qdx = 0 ; qdx < shift ; qdx += 1) {
fprintf(xnf, "(net U%uC%uR%uN (joined"
" (portRef O (instanceRef U%uC%uR%u))"
" (portRef I0 (instanceRef U%uC%uR%u))))\n",
edif_uref, sdx, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx);
fprintf(xnf, "(instance U%uC%uR%uG"
" (viewRef net"
" (cellRef GND (libraryRef VIRTEX))))\n",
edif_uref, sdx+1, qdx);
fprintf(xnf, "(net U%uC%uR%uGN (joined"
" (portRef I1 (instanceRef U%uC%uR%u))"
" (portRef GROUND (instanceRef U%uC%uR%uG))))\n",
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx);
}
for (qdx = shift ; qdx < width ; qdx += 1) {
fprintf(xnf, "(net U%uC%uR%uN (joined"
" (portRef O (instanceRef U%uC%uR%u))"
" (portRef I0 (instanceRef U%uC%uR%u))"
" (portRef I1 (instancdRef U%uC%uR%u))))\n",
edif_uref, sdx, qdx,
edif_uref, sdx, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx - shift);
}
}
}
const struct device_s d_virtex_edif = {
edif_show_header,
edif_show_footer,
@@ -1057,13 +1591,27 @@ const struct device_s d_virtex_edif = {
edif_show_generic_dff,
edif_show_virtex_eq,
edif_show_virtex_eq,
virtex_show_cmp_ge,
edif_show_virtex_mux,
edif_show_virtex_add
edif_show_virtex_add,
edif_show_virtex_add,
virtex_show_shiftl,
0 /* show_shiftr */
};
/*
* $Log: d-virtex.c,v $
* Revision 1.16 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.15 2002/09/15 21:52:19 steve
* Generate code for 8:1 muxes msing F5 and F6 muxes.
*
* Revision 1.14 2002/09/14 05:19:19 steve
* Generate Virtex code for 4:1 mux slices.
*
* Revision 1.13 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
@@ -1078,37 +1626,5 @@ const struct device_s d_virtex_edif = {
*
* Revision 1.9 2001/09/16 01:48:16 steve
* Suppor the PAD attribute on signals.
*
* Revision 1.8 2001/09/15 18:27:04 steve
* Make configure detect malloc.h
*
* Revision 1.7 2001/09/15 05:06:04 steve
* Support != in virtex code generator.
*
* Revision 1.6 2001/09/14 04:17:20 steve
* Add XOR and XNOR gates.
*
* Revision 1.5 2001/09/12 04:35:25 steve
* Xilinx uses GROUND and VCC as pin names for the
* GND and VCC devices.
*
* Connect the top end of the EQ chain to the MUXCY
* instead of to the LUT. The MUXCY has the real output.
*
* Revision 1.4 2001/09/11 05:52:31 steve
* Use carry mux to implement wide identity compare,
* Place property item in correct place in LUT cell list.
*
* Revision 1.3 2001/09/10 03:48:34 steve
* Add 4 wide identity compare.
*
* Revision 1.2 2001/09/09 22:23:28 steve
* Virtex support for mux devices and adders
* with carry chains. Also, make Virtex specific
* implementations of primitive logic.
*
* Revision 1.1 2001/09/06 04:28:40 steve
* Separate the virtex and generic-edif code generators.
*
*/
+10 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: device.h,v 1.9 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: device.h,v 1.10 2002/10/28 02:05:56 steve Exp $"
#endif
# include <ivl_target.h>
@@ -50,10 +50,15 @@ struct device_s {
/* These methods show various comparators */
void (*show_cmp_eq)(ivl_lpm_t net);
void (*show_cmp_ne)(ivl_lpm_t net);
void (*show_cmp_ge)(ivl_lpm_t net);
/* This method draws MUX devices */
void (*show_mux)(ivl_lpm_t net);
/* This method draws ADD devices */
void (*show_add)(ivl_lpm_t net);
void (*show_sub)(ivl_lpm_t net);
/* These methods draw SHIFT devices */
void (*show_shiftl)(ivl_lpm_t net);
void (*show_shiftr)(ivl_lpm_t net);
};
/*
@@ -68,6 +73,10 @@ extern device_t device_from_arch(const char*arch);
/*
* $Log: device.h,v $
* Revision 1.10 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.9 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+41 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: gates.c,v 1.9 2002/08/12 01:35:03 steve Exp $"
#ident "$Id: gates.c,v 1.10 2002/10/28 02:05:56 steve Exp $"
#endif
# include <ivl_target.h>
@@ -42,6 +42,15 @@ static void show_gate_lpm(ivl_lpm_t net)
device->show_add(net);
break;
case IVL_LPM_SUB:
if (device->show_sub == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SUB not supported"
" by this target.\n");
return;
}
device->show_sub(net);
break;
case IVL_LPM_CMP_EQ:
if (device->show_cmp_eq == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_EQ not supported"
@@ -60,6 +69,15 @@ static void show_gate_lpm(ivl_lpm_t net)
device->show_cmp_ne(net);
break;
case IVL_LPM_CMP_GE:
if (device->show_cmp_ge == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GE not supported"
" by this target.\n");
return;
}
device->show_cmp_ge(net);
break;
case IVL_LPM_FF:
if (device->show_dff == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_FF not supported"
@@ -78,6 +96,24 @@ static void show_gate_lpm(ivl_lpm_t net)
device->show_mux(net);
break;
case IVL_LPM_SHIFTL:
if (device->show_shiftl == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTL not supported"
" by this target.\n");
return;
}
device->show_shiftl(net);
break;
case IVL_LPM_SHIFTR:
if (device->show_shiftr == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTR not supported"
" by this target.\n");
return;
}
device->show_shiftr(net);
break;
default:
fprintf(stderr, "fpga.tgt: unknown LPM type %u\n",
ivl_lpm_type(net));
@@ -100,6 +136,10 @@ int show_scope_gates(ivl_scope_t net, void*x)
/*
* $Log: gates.c,v $
* Revision 1.10 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.9 2002/08/12 01:35:03 steve
* conditional ident string using autoconfig.
*
+38 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.66 2002/08/12 01:35:03 steve Exp $"
#ident "$Id: stub.c,v 1.70 2002/10/23 01:45:24 steve Exp $"
#endif
# include "config.h"
@@ -182,8 +182,25 @@ static void show_lpm(ivl_lpm_t net)
fprintf(out, " LPM_FF %s: <width=%u>\n",
ivl_lpm_name(net), width);
fprintf(out, " clk: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)));
if (ivl_lpm_enable(net))
fprintf(out, " clk: %s CE: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)),
ivl_nexus_name(ivl_lpm_enable(net)));
else
fprintf(out, " clk: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)));
if (ivl_lpm_async_clr(net))
fprintf(out, " Aclr: %s\n",
ivl_nexus_name(ivl_lpm_async_clr(net)));
if (ivl_lpm_async_set(net)) {
fprintf(out, " Aset: %s\n",
ivl_nexus_name(ivl_lpm_async_set(net)));
if (ivl_lpm_aset_value(net))
show_expression(ivl_lpm_aset_value(net), 10);
}
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Data %u: %s\n", idx,
@@ -476,6 +493,8 @@ static void show_signal(ivl_signal_t net)
case IVL_SIT_SUPPLY1:
type = "supply1";
break;
default:
break;
}
switch (ivl_signal_port(net)) {
@@ -491,6 +510,9 @@ static void show_signal(ivl_signal_t net)
case IVL_SIP_INOUT:
port = "inout ";
break;
case IVL_SIP_NONE:
break;
}
fprintf(out, " %s %s %s[%u] %s\n", type, sign, port,
@@ -706,6 +728,19 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.70 2002/10/23 01:45:24 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.69 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.68 2002/09/18 03:33:10 steve
* Fix switch case warnings.
*
* Revision 1.67 2002/09/16 00:28:25 steve
* Display FF enables.
*
* Revision 1.66 2002/08/12 01:35:03 steve
* conditional ident string using autoconfig.
*
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.10 2002/08/12 00:27:10 steve Exp $"
#ident "$Id: Makefile.in,v 1.11 2002/09/27 16:33:34 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,7 +50,7 @@ all: vvp.tgt
$(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = vvp.o draw_mux.o eval_expr.o vvp_process.o vvp_scope.o
O = vvp.o draw_mux.o eval_expr.o vector.o vvp_process.o vvp_scope.o
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
+12 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_mux.c,v 1.4 2002/08/12 01:35:03 steve Exp $"
#ident "$Id: draw_mux.c,v 1.5 2002/08/29 03:04:01 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -28,6 +28,10 @@
# include <stdlib.h>
# include <string.h>
/*
* This draws a general mux, a slice at a time. Use MUXX so that
* unknows lead to unknown output.
*/
static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
{
unsigned sel = ivl_lpm_selects(net);
@@ -55,7 +59,7 @@ static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
select vector. */
for (idx = 0 ; idx < size ; idx += 2) {
fprintf(vvp_out, "L_%s/%u/%u/%u .functor MUXZ, ",
fprintf(vvp_out, "L_%s/%u/%u/%u .functor MUXX, ",
vvp_mangle_id(ivl_lpm_name(net)), slice, sel, idx);
{
@@ -76,7 +80,7 @@ static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
fprintf(vvp_out, ", C<1>;\n");
}
/* Draw the tree of MUXZ devices to connect the inner tree
/* Draw the tree of MUXX devices to connect the inner tree
nodes. */
for (seldx = 1 ; seldx < (sel-1) ; seldx += 1) {
unsigned level = sel - seldx;
@@ -84,7 +88,7 @@ static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
s = ivl_lpm_select(net, seldx);
for (idx = 0 ; idx < size ; idx += span) {
fprintf(vvp_out, "L_%s/%u/%u/%u .functor MUXZ, ",
fprintf(vvp_out, "L_%s/%u/%u/%u .functor MUXX, ",
vvp_mangle_id(ivl_lpm_name(net)), slice, level, idx);
fprintf(vvp_out, "L_%s/%u/%u/%u, ",
@@ -106,7 +110,7 @@ static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
s = ivl_lpm_select(net, sel-1);
fprintf(vvp_out, "L_%s/%u .functor MUXZ, ",
fprintf(vvp_out, "L_%s/%u .functor MUXX, ",
vvp_mangle_id(ivl_lpm_name(net)), slice);
fprintf(vvp_out, "L_%s/%u/2/0, ",
@@ -172,6 +176,9 @@ void draw_lpm_mux(ivl_lpm_t net)
/*
* $Log: draw_mux.c,v $
* Revision 1.5 2002/08/29 03:04:01 steve
* Generate x out for x select on wide muxes.
*
* Revision 1.4 2002/08/12 01:35:03 steve
* conditional ident string using autoconfig.
*
+235 -218
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.73 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: eval_expr.c,v 1.82 2002/10/20 02:55:37 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -28,71 +28,6 @@
# include <stdlib.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);
}
/*
* This clears a vector that was previously allocated by
* allocate_vector. That is, it unmarks all the bits of the map that
* represent this vector.
*
* If the vector is based in one of 4 constant bit values, then there
* are no bits to clear. If the vector is based in the 4-8 result
* area, then someone is broken.
*/
void clr_vector(struct vector_info vec)
{
unsigned idx;
if (vec.base < 4)
return;
assert(vec.base >= 8);
for (idx = 0 ; idx < vec.wid ; idx += 1)
clr_bit(vec.base + idx);
}
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;
}
int number_is_unknown(ivl_expr_t ex)
{
@@ -162,30 +97,44 @@ unsigned long get_number_immediate(ivl_expr_t ex)
return imm;
}
/*
* The STUFF_OK_XZ bit is true if the output is going to be further
* processed so that x and z values are equivilent. This may allow for
* new optimizations.
*/
static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
ivl_expr_t le,
ivl_expr_t re)
ivl_expr_t re,
int stuff_ok_flag)
{
unsigned wid;
struct vector_info lv;
unsigned long imm = get_number_immediate(re);
wid = ivl_expr_width(le);
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
switch (ivl_expr_opcode(exp)) {
case 'E': /* === */
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 6;
lv.wid = 1;
break;
case 'e': /* == */
/* If this is a single bit being compared to 1, and the
output doesn't care about x vs z, then just return
the value itself. */
if ((stuff_ok_flag&STUFF_OK_XZ) && (lv.wid == 1) && (imm == 1))
break;
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 4;
lv.wid = 1;
break;
@@ -193,16 +142,24 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
case 'N': /* !== */
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 6;
lv.wid = 1;
fprintf(vvp_out, " %%inv 6, 1;\n");
break;
case 'n': /* != */
/* If this is a single bit being compared to 0, and the
output doesn't care about x vs z, then just return
the value itself. */
if ((stuff_ok_flag&STUFF_OK_XZ) && (lv.wid == 1) && (imm == 0))
break;
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 4;
lv.wid = 1;
fprintf(vvp_out, " %%inv 4, 1;\n");
@@ -212,21 +169,39 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
assert(0);
}
/* In the special case that 47 bits are ok, and this really is
a single bit value, then we are done. */
if ((lv.wid == 1) && (ewid == 1) && (stuff_ok_flag&STUFF_OK_47))
return lv;
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
{ unsigned short base = allocate_vector(ewid);
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
lv.base = base;
lv.wid = ewid;
if (ewid > 1)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1);
if (lv.base < 8) {
unsigned short base = allocate_vector(ewid);
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
lv.base = base;
lv.wid = ewid;
if (ewid > 1)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1);
} else if (lv.wid < ewid) {
unsigned short base = allocate_vector(ewid);
clr_vector(lv);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", base,
lv.base, lv.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
base+lv.wid, ewid-lv.wid);
lv.base = base;
lv.wid = ewid;
}
return lv;
}
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
unsigned ewid,
int stuff_ok_flag)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
@@ -238,19 +213,19 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
if ((ivl_expr_type(re) == IVL_EX_ULONG)
&& (0 == (ivl_expr_uvalue(re) & ~0xffff)))
return draw_eq_immediate(exp, ewid, le, re);
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
if ((ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re))
&& number_is_immediate(re, 16))
return draw_eq_immediate(exp, ewid, le, re);
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
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);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&STUFF_OK_XZ);
switch (ivl_expr_opcode(exp)) {
case 'E': /* === */
@@ -316,6 +291,10 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
assert(0);
}
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
return lv;
}
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
@@ -339,7 +318,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid)
struct vector_info rv;
lv = draw_eval_expr(le);
lv = draw_eval_expr(le, STUFF_OK_XZ);
if ((lv.base >= 4) && (lv.wid > 1)) {
struct vector_info tmp;
@@ -351,7 +330,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid)
lv = tmp;
}
rv = draw_eval_expr(re);
rv = draw_eval_expr(re, STUFF_OK_XZ);
if ((rv.base >= 4) && (rv.wid > 1)) {
struct vector_info tmp;
clr_vector(rv);
@@ -411,7 +390,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
struct vector_info lv;
struct vector_info rv;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
/* if the left operand has width, then evaluate the single-bit
logical equivilent. */
@@ -425,7 +404,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
lv = tmp;
}
rv = draw_eval_expr_wid(re, wid);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
/* if the right operand has width, then evaluate the single-bit
logical equivilent. */
@@ -481,7 +460,9 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
return lv;
}
static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
unsigned wid,
int stuff_ok_flag)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
@@ -495,8 +476,8 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
if (ivl_expr_width(re) > owid)
owid = ivl_expr_width(re);
lv = draw_eval_expr_wid(le, owid);
rv = draw_eval_expr_wid(re, owid);
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
switch (ivl_expr_opcode(exp)) {
case 'G':
@@ -532,6 +513,12 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
clr_vector(lv);
clr_vector(rv);
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
lv.base = 5;
lv.wid = wid;
return lv;
}
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
@@ -555,8 +542,8 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
struct vector_info lv;
struct vector_info rv;
lv = draw_eval_expr_wid(le, wid);
rv = draw_eval_expr_wid(re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
/* The result goes into the left operand, and that is returned
as the result. The instructions do not allow the lv value
@@ -595,6 +582,16 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
lv.base, rv.base, wid);
break;
case 'A': /* NAND (~&) */
fprintf(vvp_out, " %%nand %u, %u, %u;\n",
lv.base, rv.base, wid);
break;
case 'O': /* NOR (~|) */
fprintf(vvp_out, " %%nor %u, %u, %u;\n",
lv.base, rv.base, wid);
break;
case 'X': /* exclusive nor (~^) */
fprintf(vvp_out, " %%xnor %u, %u, %u;\n",
lv.base, rv.base, wid);
@@ -654,7 +651,7 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
default: {
struct vector_info rv;
rv = draw_eval_expr(re);
rv = draw_eval_expr(re, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n",
rv.base, rv.wid);
clr_vector(rv);
@@ -662,7 +659,7 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
}
}
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, 0);
switch (ivl_expr_opcode(exp)) {
@@ -688,7 +685,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
struct vector_info lv;
unsigned long imm;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
imm = get_number_immediate(re);
@@ -725,7 +722,7 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
struct vector_info lv;
unsigned long imm;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
imm = get_number_immediate(re);
@@ -743,7 +740,7 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
struct vector_info lv;
unsigned long imm;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
imm = get_number_immediate(re);
@@ -789,8 +786,8 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
&& number_is_immediate(re, 16))
return draw_mul_immediate(le, re, wid);
lv = draw_eval_expr_wid(le, wid);
rv = draw_eval_expr_wid(re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
assert(rv.wid == wid);
@@ -840,9 +837,12 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
return lv;
}
static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_binary_expr(ivl_expr_t exp,
unsigned wid,
int stuff_ok_flag)
{
struct vector_info rv;
int stuff_ok_used_flag = 0;
switch (ivl_expr_opcode(exp)) {
case 'a': /* && (logical and) */
@@ -853,14 +853,16 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
case 'e': /* == */
case 'N': /* !== */
case 'n': /* != */
rv = draw_binary_expr_eq(exp, wid);
rv = draw_binary_expr_eq(exp, wid, stuff_ok_flag);
stuff_ok_used_flag = 1;
break;
case '<':
case '>':
case 'L': /* <= */
case 'G': /* >= */
rv = draw_binary_expr_le(exp, wid);
rv = draw_binary_expr_le(exp, wid, stuff_ok_flag);
stuff_ok_used_flag = 1;
break;
case '+':
@@ -883,7 +885,9 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
case '&':
case '|':
case '^':
case 'X':
case 'A': /* NAND (~&) */
case 'O': /* NOR (~|) */
case 'X': /* XNOR (~^) */
rv = draw_binary_expr_logic(exp, wid);
break;
@@ -893,6 +897,21 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
assert(0);
}
/* Mark in the lookaside that this value is done. If any OK
flags besides the STUFF_OK_47 flag are set, then the result
may not be a pure one, so clear the lookaside for the range
instead of setting in to the new expression result.
The stuff_ok_used_flag tells me if the stuff_ok_flag was
even used by anything. If not, then I can ignore it in the
following logic. */
if (rv.base >= 8) {
if (stuff_ok_used_flag && (stuff_ok_flag & ~STUFF_OK_47))
save_expression_lookaside(rv.base, 0, wid);
else
save_expression_lookaside(rv.base, exp, wid);
}
return rv;
}
@@ -904,7 +923,7 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
/* Evaluate the bit select expression and save the result into
index register 0. */
res = draw_eval_expr(sel);
res = draw_eval_expr(sel, 0);
fprintf(vvp_out, " %%ix/get 0, %u,%u;\n", res.base, res.wid);
clr_vector(res);
@@ -924,6 +943,8 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
break;
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -961,10 +982,22 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
ivl_expr_t arg = ivl_expr_parm(exp, idx-1);
unsigned awid = ivl_expr_width(arg);
/* Evaluate this sub expression. */
struct vector_info avec = draw_eval_expr_wid(arg, awid);
unsigned trans;
struct vector_info avec;
unsigned trans = awid;
/* Try to locate the subexpression in the
lookaside map. */
avec.base = allocate_vector_exp(arg, awid);
avec.wid = awid;
/* If it's not in the lookaside map, then
evaluate the expression here. */
if (avec.base == 0) {
/* Evaluate this sub expression. */
avec = draw_eval_expr_wid(arg, awid, 0);
}
trans = awid;
if ((off + awid) > wid)
trans = wid - off;
@@ -987,6 +1020,10 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
res.base+off, wid-off);
}
/* Save the accumulated result in the lookaside map. */
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1072,6 +1109,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
if (idx < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1119,6 +1159,9 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
if (idx < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1139,8 +1182,16 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
if (swid > wid)
swid = wid;
res.base = allocate_vector(wid);
res.wid = wid;
res.base = allocate_vector_exp(exp, wid);
res.wid = wid;
if (res.base != 0)
return res;
if (res.base == 0) {
res.base = allocate_vector(wid);
res.wid = wid;
save_expression_lookaside(res.base, exp, wid);
}
for (idx = 0 ; idx < swid ; idx += 1)
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
@@ -1191,7 +1242,7 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
break;
}
default: {
struct vector_info addr = draw_eval_expr(ae);
struct vector_info addr = draw_eval_expr(ae, 0);
fprintf(vvp_out, " %%ix/get 3, %u, %u;\n",
addr.base, addr.wid);
clr_vector(addr);
@@ -1231,6 +1282,9 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1241,7 +1295,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
ivl_expr_t shift = ivl_expr_oper2(exp);
/* Evaluate the sub-expression. */
subv = draw_eval_expr(sube);
subv = draw_eval_expr(sube, 0);
/* Any bit select of a constant zero is another constant zero,
so short circuit and return the value we know. */
@@ -1252,7 +1306,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
/* Evaluate the bit select base expression and store the
result into index register 0. */
shiv = draw_eval_expr(shift);
shiv = draw_eval_expr(shift, STUFF_OK_XZ);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
clr_vector(shiv);
@@ -1280,6 +1334,9 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
res = subv;
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1296,7 +1353,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
lab_false = local_count++;
lab_out = local_count++;
tmp = draw_eval_expr(cond);
tmp = draw_eval_expr(cond, STUFF_OK_XZ);
clr_vector(tmp);
if ((tmp.base >= 4) && (tmp.wid > 1)) {
@@ -1316,32 +1373,42 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
/* Ambiguous case. Evaluate both true and false expressions,
and use %blend to merge them. */
tmp = draw_eval_expr_wid(true_ex, wid);
tmp = draw_eval_expr_wid(true_ex, wid, 0);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
clr_vector(tmp);
tmp = draw_eval_expr_wid(false_ex, wid);
tmp = draw_eval_expr_wid(false_ex, wid, 0);
fprintf(vvp_out, " %%blend %u, %u, %u;\n", res.base, tmp.base, wid);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
if (tmp.base >= 8)
clr_vector(tmp);
/* This is the true case. Just evaluate the true expression. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_true);
clear_expression_lookaside();
tmp = draw_eval_expr_wid(true_ex, wid);
tmp = draw_eval_expr_wid(true_ex, wid, 0);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
clr_vector(tmp);
if (tmp.base >= 8)
clr_vector(tmp);
/* This is the false case. Just evaluate the false expression. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_false);
clear_expression_lookaside();
tmp = draw_eval_expr_wid(false_ex, wid);
tmp = draw_eval_expr_wid(false_ex, wid, 0);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
clr_vector(tmp);
if (tmp.base >= 8)
clr_vector(tmp);
/* This is the out label. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
clear_expression_lookaside();
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1392,7 +1459,7 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
vec[vecs] = draw_eval_expr(expr);
vec[vecs] = draw_eval_expr(expr, 0);
vecs++;
}
@@ -1472,6 +1539,9 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
free(vec);
}
/* New basic block starts after VPI calls. */
clear_expression_lookaside();
fprintf(vvp_out, ";\n");
@@ -1506,7 +1576,7 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
unsigned pin, bit;
res = draw_eval_expr_wid(ivl_expr_parm(exp, idx),
ivl_signal_pins(port));
ivl_signal_pins(port), 0);
bit = res.base;
assert(res.wid <= ivl_signal_pins(port));
for (pin = 0 ; pin < res.wid ; pin += 1) {
@@ -1526,6 +1596,9 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, ", S_%s;\n", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, " %%join;\n");
/* Fresh basic block starts after the join. */
clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
@@ -1573,7 +1646,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
switch (ivl_expr_opcode(exp)) {
case '~':
res = draw_eval_expr_wid(sub, wid);
res = draw_eval_expr_wid(sub, wid, STUFF_OK_XZ);
switch (res.base) {
case 0:
res.base = 1;
@@ -1596,7 +1669,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
complement of the number. That is the 1's complement
(bitwise invert) with a 1 added in. Note that the
%sub subtracts -1 (1111...) to get %add of +1. */
res = draw_eval_expr_wid(sub, wid);
res = draw_eval_expr_wid(sub, wid, STUFF_OK_XZ);
switch (res.base) {
case 0:
res.base = 0;
@@ -1616,7 +1689,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
break;
case '!':
res = draw_eval_expr(sub);
res = draw_eval_expr(sub, STUFF_OK_XZ);
if (res.wid > 1) {
/* a ! on a vector is implemented with a reduction
nor. Generate the result into the first bit of
@@ -1668,7 +1741,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
case '&':
case '|':
case '^':
res = draw_eval_expr(sub);
res = draw_eval_expr(sub, 0);
if (res.wid > 1) {
struct vector_info tmp;
/* If the previous result is in the constant area
@@ -1715,10 +1788,14 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
assert(0);
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
struct vector_info res;
@@ -1737,7 +1814,7 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
break;
case IVL_EX_BINARY:
res = draw_binary_expr(exp, wid);
res = draw_binary_expr(exp, wid, stuff_ok_flag);
break;
case IVL_EX_BITSEL:
@@ -1784,13 +1861,41 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
return res;
}
struct vector_info draw_eval_expr(ivl_expr_t exp)
struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
{
return draw_eval_expr_wid(exp, ivl_expr_width(exp));
return draw_eval_expr_wid(exp, ivl_expr_width(exp), stuff_ok_flag);
}
/*
* $Log: eval_expr.c,v $
* Revision 1.82 2002/10/20 02:55:37 steve
* Properly set or clear expression lookaside for binary expressions.
*
* Revision 1.81 2002/09/27 20:24:42 steve
* Allow expression lookaside map to spam statements.
*
* Revision 1.80 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
* Revision 1.79 2002/09/24 04:20:32 steve
* Allow results in register bits 47 in certain cases.
*
* Revision 1.78 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.77 2002/09/13 04:09:51 steve
* single bit optimization for != in expressions,
* and expand ++ and != results if needed.
*
* Revision 1.76 2002/09/13 03:12:50 steve
* Optimize ==1 when in context where x vs z doesnt matter.
*
* Revision 1.75 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.74 2002/09/01 01:42:34 steve
* Fix leaking vthread bits in ?: eval.
*
* Revision 1.73 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
@@ -1818,93 +1923,5 @@ struct vector_info draw_eval_expr(ivl_expr_t exp)
* generate vvp labels. -tdll target does not
* used hierarchical name string to look up the
* memory objects in the design.
*
* Revision 1.66 2002/08/03 22:30:48 steve
* Eliminate use of ivl_signal_name for signal labels.
*
* Revision 1.65 2002/07/12 18:10:45 steve
* Use all bits of ?: condit expression.
*
* Revision 1.64 2002/07/01 00:52:47 steve
* Carry can propagate to the otp in addi.
*
* Revision 1.63 2002/06/02 18:57:17 steve
* Generate %cmpi/u where appropriate.
*
* Revision 1.62 2002/05/31 20:04:57 steve
* Generate %muli instructions when possible.
*
* Revision 1.61 2002/05/30 01:57:23 steve
* Use addi with wide immediate values.
*
* Revision 1.60 2002/05/29 16:29:34 steve
* Add %addi, which is faster to simulate.
*
* Revision 1.59 2002/05/07 03:49:58 steve
* Handle x case of unary ! properly.
*
* Revision 1.58 2002/04/22 02:41:30 steve
* Reduce the while loop expression if needed.
*
* Revision 1.57 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.56 2002/02/03 05:53:00 steve
* Fix parameter bit select check for magic constants.
*
* Revision 1.55 2002/01/28 00:52:42 steve
* Add support for bit select of parameters.
* This leads to a NetESelect node and the
* vvp code generator to support that.
*
* Revision 1.54 2002/01/11 05:23:05 steve
* Handle certain special cases of stime.
*
* Revision 1.53 2001/11/19 04:25:46 steve
* Handle padding out of logical values.
*
* Revision 1.52 2001/10/24 05:06:54 steve
* The ! expression returns 0 to x and z values.
*
* Revision 1.51 2001/10/18 16:41:49 steve
* Evaluate string expressions (Philip Blundell)
*
* Revision 1.50 2001/10/16 01:27:17 steve
* Generate %div instructions for binary /.
*
* Revision 1.49 2001/10/14 03:24:35 steve
* Handle constant bits in arithmetic expressions.
*
* Revision 1.48 2001/10/10 04:47:43 steve
* Support vectors as operands to logical and.
*
* Revision 1.47 2001/09/29 04:37:44 steve
* Generate code for unary minus (PR#272)
*
* Revision 1.46 2001/09/29 01:53:22 steve
* Fix the size of unsized constant operants to compare (PR#274)
*
* Revision 1.45 2001/09/20 03:46:38 steve
* Handle short l-values to concatenation.
*
* Revision 1.44 2001/09/15 18:27:04 steve
* Make configure detect malloc.h
*
* Revision 1.43 2001/08/31 01:37:56 steve
* Handle update in place of repeat constants.
*
* Revision 1.42 2001/08/23 02:54:15 steve
* Handle wide assignment to narrow return value.
*
* Revision 1.41 2001/08/03 17:06:10 steve
* More detailed messages about unsupported things.
*
* Revision 1.40 2001/07/27 04:51:45 steve
* Handle part select expressions as variants of
* NetESignal/IVL_EX_SIGNAL objects, instead of
* creating new and useless temporary signals.
*
* Revision 1.39 2001/07/27 02:41:56 steve
* Fix binding of dangling function ports. do not elide them.
*/
+211
View File
@@ -0,0 +1,211 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vector.c,v 1.1 2002/09/27 16:33:34 steve Exp $"
#endif
# include "vvp_priv.h"
# include <assert.h>
static struct allocation_score_s {
ivl_expr_t exp;
unsigned bit :16;
unsigned alloc : 1;
} allocation_map[0x10000] = { {0} };
/* This is the largest bit to have lookaside values. */
static unsigned lookaside_top = 0;
static inline int peek_bit(unsigned addr)
{
return allocation_map[addr].alloc;
}
static inline void set_bit(unsigned addr)
{
allocation_map[addr].alloc = 1;
}
static inline void clr_bit(unsigned addr)
{
allocation_map[addr].alloc = 0;
}
/*
* This clears a vector that was previously allocated by
* allocate_vector. That is, it unmarks all the bits of the map that
* represent this vector.
*
* If the vector is based in one of 4 constant bit values, then there
* are no bits to clear. If the vector is based in the 4-8 result
* area, then someone is broken.
*/
void clr_vector(struct vector_info vec)
{
unsigned idx;
if (vec.base < 4)
return;
assert(vec.base >= 8);
for (idx = 0 ; idx < vec.wid ; idx += 1)
clr_bit(vec.base + idx);
}
/*
* This unconditionally allocates a stretch of bits from the register
* set. It never returns a bit addressed <8 (0-3 are constant, 4-7 are
* condition codes).
*/
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) {
allocation_map[base+idx].alloc = 1;
allocation_map[base+idx].exp = 0;
}
return base;
}
/*
* This clears the expression cache of the allocation map. It is
* called to prevent reuse of existing expressions, normally at the
* start of a basic block.
*/
void clear_expression_lookaside(void)
{
unsigned idx;
for (idx = 0 ; idx < lookaside_top ; idx += 1) {
allocation_map[idx].exp = 0;
}
lookaside_top = 0;
}
void save_expression_lookaside(unsigned short addr, ivl_expr_t exp,
unsigned short wid)
{
unsigned idx;
assert(addr >= 8);
assert((addr+wid) <= 0x10000);
for (idx = 0 ; idx < wid ; idx += 1) {
allocation_map[addr+idx].exp = exp;
allocation_map[addr+idx].bit = idx;
}
if ((addr+wid) > lookaside_top)
lookaside_top = addr+wid;
}
static int compare_exp(ivl_expr_t l, ivl_expr_t r)
{
if (! (l && r))
return 0;
if (l == r)
return 1;
if (ivl_expr_type(l) != ivl_expr_type(r))
return 0;
switch (ivl_expr_type(l)) {
case IVL_EX_SIGNAL:
if (ivl_expr_signal(l) != ivl_expr_signal(r))
return 0;
if (ivl_expr_lsi(l) != ivl_expr_lsi(r))
return 0;
if (ivl_expr_width(l) != ivl_expr_width(r))
return 0;
return 1;
default:
break;
}
return 0;
}
static unsigned short find_expression_lookaside(ivl_expr_t exp,
unsigned short wid)
{
unsigned top;
unsigned idx, match;
if (lookaside_top <= wid)
return 0;
top = lookaside_top - wid + 1;
assert(exp);
match = 0;
for (idx = 8 ; idx < top ; idx += 1) {
if (! compare_exp(allocation_map[idx].exp, exp)) {
match = 0;
continue;
}
if (allocation_map[idx].bit != match) {
match = 0;
continue;
}
match += 1;
if (match == wid)
return idx-match+1;
}
return 0;
}
unsigned short allocate_vector_exp(ivl_expr_t exp, unsigned short wid)
{
unsigned idx;
unsigned short la = find_expression_lookaside(exp, wid);
for (idx = 0 ; idx < wid ; idx += 1)
if (allocation_map[la+idx].alloc)
return 0;
for (idx = 0 ; idx < wid ; idx += 1)
allocation_map[la+idx].alloc = 1;
return la;
}
/*
* $Log: vector.c,v $
* Revision 1.1 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
*/
+63 -3
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_priv.h,v 1.19 2002/08/27 05:39:57 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $"
#endif
# include "ivl_target.h"
@@ -83,14 +83,28 @@ extern void draw_input_from_net(ivl_nexus_t nex);
* 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.
*
* The stuff_ok_flag is normally empty. Bits in the bitmask are set
* true in cases where certain special situations are allows. This
* might allow deeper expressions to make assumptions about the
* caller.
*
* STUFF_OK_XZ -- This bit is set if the code processing the result
* doesn't distinguish between x and z values.
*
* STUFF_OK_47 -- This bit is set if the node is allowed to leave a
* result in any of the 4-7 vthread 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 struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag);
extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w,
int stuff_ok_flag);
#define STUFF_OK_XZ 0x0001
#define STUFF_OK_47 0x0002
/*
* This function draws code to evaluate the index expression exp for
@@ -100,9 +114,46 @@ extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w);
*/
extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
/*
* These functions manage vector allocation in the thread register
* space. They presume that we work on one thread at a time, to
* completion.
*
* allocate_vector
* Return the base of an allocated vector in the thread. The bits
* are marked allocated in the process.
*
* clr_bector
* Clear a vector previously allocated.
*
* The thread vector allocator also keeps a lookaside of expression
* results that are stored in register bit. This lookaside can be used
* by the code generator to notice that certain expression bits are
* already calculated, and can be reused.
*
* clear_expression_lookaside
* Clear the lookaside tables for the current thread.
*
* save_expression_lookaside
* Mark the given expression as available in the given register
* bits. This remains until the lookaside is cleared.
*
* allocate_vector_exp
* This function attempts to locate the expression in the
* lookaside. If it finds it, return a reallocated base for the
* expression. Otherwise, return 0.
*/
extern unsigned short allocate_vector(unsigned short wid);
extern void clr_vector(struct vector_info vec);
extern void clear_expression_lookaside(void);
extern void save_expression_lookaside(unsigned short addr,
ivl_expr_t exp,
unsigned short wid);
extern unsigned short allocate_vector_exp(ivl_expr_t exp,
unsigned short wid);
extern int number_is_unknown(ivl_expr_t ex);
extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid);
extern unsigned long get_number_immediate(ivl_expr_t ex);
@@ -115,6 +166,15 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.22 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
* Revision 1.21 2002/09/24 04:20:32 steve
* Allow results in register bits 47 in certain cases.
*
* Revision 1.20 2002/09/13 03:12:50 steve
* Optimize ==1 when in context where x vs z doesnt matter.
*
* Revision 1.19 2002/08/27 05:39:57 steve
* Fix l-value indexing of memories and vectors so that
* an unknown (x) index causes so cell to be addresses.
+141 -139
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_process.c,v 1.65 2002/08/27 05:39:57 steve Exp $"
#ident "$Id: vvp_process.c,v 1.71 2002/09/27 20:24:42 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -131,14 +131,14 @@ static void assign_to_memory(ivl_memory_t mem, unsigned idx,
*/
static void calculate_into_x0(ivl_expr_t expr)
{
struct vector_info vec = draw_eval_expr(expr);
struct vector_info vec = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", vec.base, vec.wid);
clr_vector(vec);
}
static void calculate_into_x1(ivl_expr_t expr)
{
struct vector_info vec = draw_eval_expr(expr);
struct vector_info vec = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get 1, %u, %u;\n", vec.base, vec.wid);
clr_vector(vec);
}
@@ -210,14 +210,16 @@ static int show_stmt_assign(ivl_statement_t net)
set_to_lvariable(lval, idx, 0);
}
if (skip_set_flag)
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
return 0;
}
{ struct vector_info res = draw_eval_expr(rval);
{ struct vector_info res = draw_eval_expr(rval, 0);
unsigned wid = res.wid;
unsigned lidx;
unsigned cur_rbit = 0;
@@ -265,12 +267,14 @@ static int show_stmt_assign(ivl_statement_t net)
else
set_to_lvariable(lval, idx, 0);
if (skip_set_flag)
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
clr_vector(res);
if (res.base > 3)
clr_vector(res);
}
@@ -304,54 +308,78 @@ static int show_stmt_assign_nb(ivl_statement_t net)
calculate_into_x1(del);
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
unsigned skip_set = transient_id++;
unsigned skip_set_flag = 0;
unsigned idx;
unsigned bit_limit = wid - cur_rbit;
lval = ivl_stmt_lval(net, lidx);
/* If there is a mux for the lval, calculate the
value and write it into index0. */
if (ivl_lval_mux(lval))
if (ivl_lval_mux(lval)) {
calculate_into_x0(ivl_lval_mux(lval));
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
skip_set_flag = 1;
}
mem = ivl_lval_mem(lval);
if (mem)
if (mem) {
draw_memory_index_expr(mem, ivl_lval_idx(lval));
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
skip_set_flag = 1;
}
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
for (idx = 0 ; idx < bit_limit ; idx += 1) {
if (mem)
if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
assign_to_memory(mem, idx,
bitchar_to_idx(bits[cur_rbit]),
delay);
else if (del != 0)
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
1, 1);
else
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
cur_rbit += 1;
cur_rbit += 1;
}
for (idx = bit_limit
; idx < ivl_lval_pins(lval)
; idx += 1) {
assign_to_memory(mem, idx, 0, delay);
}
} else {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
if (del != 0)
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
1, 1);
else
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
cur_rbit += 1;
}
for (idx = bit_limit
; idx < ivl_lval_pins(lval)
; idx += 1) {
if (del != 0)
assign_to_lvariable(lval, idx, 0,
1, 1);
else
assign_to_lvariable(lval, idx, 0,
delay, 0);
}
}
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
if (mem)
assign_to_memory(mem, idx, 0, delay);
else if (del != 0)
assign_to_lvariable(lval, idx, 0,
1, 1);
else
assign_to_lvariable(lval, idx, 0,
delay, 0);
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
return 0;
}
{ struct vector_info res = draw_eval_expr(rval);
{ struct vector_info res = draw_eval_expr(rval, 0);
unsigned wid = res.wid;
unsigned lidx;
unsigned cur_rbit = 0;
@@ -360,19 +388,26 @@ static int show_stmt_assign_nb(ivl_statement_t net)
calculate_into_x1(del);
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
unsigned skip_set = transient_id++;
unsigned skip_set_flag = 0;
unsigned idx;
unsigned bit_limit = wid - cur_rbit;
lval = ivl_stmt_lval(net, lidx);
/* If there is a mux for the lval, calculate the
value and write it into index0. */
if (ivl_lval_mux(lval))
if (ivl_lval_mux(lval)) {
calculate_into_x0(ivl_lval_mux(lval));
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
skip_set_flag = 1;
}
mem = ivl_lval_mem(lval);
if (mem)
if (mem) {
draw_memory_index_expr(mem, ivl_lval_idx(lval));
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
skip_set_flag = 1;
}
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
@@ -401,9 +436,15 @@ static int show_stmt_assign_nb(ivl_statement_t net)
else
assign_to_lvariable(lval, idx, 0, delay, 0);
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
clr_vector(res);
if (res.base > 3)
clr_vector(res);
}
return 0;
@@ -445,6 +486,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
fprintf(vvp_out, " %%end;\n");
fprintf(vvp_out, "t_%u %%join;\n", out_id);
clear_expression_lookaside();
return rc;
}
@@ -453,7 +495,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
{
ivl_expr_t exp = ivl_stmt_cond_expr(net);
struct vector_info cond = draw_eval_expr(exp);
struct vector_info cond = draw_eval_expr(exp, 0);
unsigned count = ivl_stmt_case_count(net);
unsigned local_base = local_count;
@@ -496,7 +538,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
/* Oh well, do this case the hard way. */
cvec = draw_eval_expr_wid(cex, cond.wid);
cvec = draw_eval_expr_wid(cex, cond.wid, 0);
assert(cvec.wid == cond.wid);
switch (ivl_statement_type(net)) {
@@ -550,6 +592,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
continue;
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx);
clear_expression_lookaside();
show_statement(cst, sscope);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count,
@@ -557,8 +600,10 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
}
/* The out of the case. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+count);
clear_expression_lookaside();
return 0;
}
@@ -616,7 +661,7 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
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);
struct vector_info cond = draw_eval_expr(exp, STUFF_OK_XZ|STUFF_OK_47);
assert(cond.wid == 1);
@@ -627,21 +672,26 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
thread_count, lab_false, cond.base);
/* Done with the condition expression. */
clr_vector(cond);
if (cond.base >= 8)
clr_vector(cond);
if (ivl_stmt_cond_true(net))
rc += show_statement(ivl_stmt_cond_true(net), sscope);
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);
clear_expression_lookaside();
rc += show_statement(ivl_stmt_cond_false(net), sscope);
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_out);
clear_expression_lookaside();
} else {
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_false);
clear_expression_lookaside();
}
return rc;
@@ -662,6 +712,9 @@ static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope)
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
fprintf(vvp_out, " %%delay %lu;\n", delay);
/* Lots of things can happen during a delay. */
clear_expression_lookaside();
rc += show_statement(stmt, sscope);
return rc;
@@ -679,12 +732,14 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
ivl_expr_t exp = ivl_stmt_delay_expr(net);
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
{ struct vector_info del = draw_eval_expr(exp);
{ struct vector_info del = draw_eval_expr(exp, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", del.base, del.wid);
clr_vector(del);
}
fprintf(vvp_out, " %%delayx 0;\n");
/* Lots of things can happen during a delay. */
clear_expression_lookaside();
rc += show_statement(stmt, sscope);
return rc;
@@ -773,12 +828,14 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
for (idx = 0 ; idx < cnt-1 ; idx += 1) {
fprintf(vvp_out, "t_%u ;\n", id_base+idx);
clear_expression_lookaside();
rc += show_statement(ivl_stmt_block_stmt(net, idx), sscope);
fprintf(vvp_out, " %%end;\n");
}
/* This is the label for the out. Use this to branch around
the implementations of all the child threads. */
clear_expression_lookaside();
fprintf(vvp_out, "t_%u ;\n", out);
return rc;
@@ -833,11 +890,12 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
int rc = 0;
unsigned lab_top = local_count++, lab_out = local_count++;
ivl_expr_t exp = ivl_stmt_cond_expr(net);
struct vector_info cnt = draw_eval_expr(exp);
struct vector_info cnt = draw_eval_expr(exp, 0);
/* Test that 0 < expr */
fprintf(vvp_out, "T_%u.%u %%cmp/u 0, %u, %u;\n", thread_count,
lab_top, cnt.base, cnt.wid);
clear_expression_lookaside();
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, lab_out);
/* This adds -1 (all ones in 2's complement) to the count. */
fprintf(vvp_out, " %%add %u, 1, %u;\n", cnt.base, cnt.wid);
@@ -846,6 +904,7 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top);
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out);
clear_expression_lookaside();
clr_vector(cnt);
@@ -870,6 +929,7 @@ static int show_stmt_utask(ivl_statement_t net)
fprintf(vvp_out, ", S_%s;\n",
vvp_mangle_id(ivl_scope_name(task)));
fprintf(vvp_out, " %%join;\n");
clear_expression_lookaside();
return 0;
}
@@ -879,6 +939,10 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
fprintf(vvp_out, " %%wait E_%s;\n",
vvp_mangle_id(ivl_event_name(ev)));
/* Always clear the expression lookaside after a
%wait. Anything can happen while the thread is waiting. */
clear_expression_lookaside();
return show_statement(ivl_stmt_sub_stmt(net), sscope);
}
@@ -920,18 +984,23 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
unsigned top_label = local_count++;
unsigned out_label = local_count++;
/* Start the loop. The top of the loop starts a basic block
because it can be entered from above or from the bottom of
the loop. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, top_label);
clear_expression_lookaside();
/* Draw the evaluation of the condition expression, and test
the result. If the expression evaluates to false, then
branch to the out label. */
cvec = draw_eval_expr(ivl_stmt_cond_expr(net));
cvec = draw_eval_expr(ivl_stmt_cond_expr(net), STUFF_OK_XZ|STUFF_OK_47);
if (cvec.wid > 1)
cvec = reduction_or(cvec);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, %u;\n",
thread_count, out_label, cvec.base);
clr_vector(cvec);
if (cvec.base >= 8)
clr_vector(cvec);
/* Draw the body of the loop. */
rc += show_statement(ivl_stmt_sub_stmt(net), sscope);
@@ -940,6 +1009,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
test is repeased, and also draw the out label. */
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, top_label);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, out_label);
clear_expression_lookaside();
return rc;
}
@@ -953,6 +1023,7 @@ static int show_system_task_call(ivl_statement_t net)
if (parm_count == 0) {
fprintf(vvp_out, " %%vpi_call \"%s\";\n", ivl_stmt_name(net));
clear_expression_lookaside();
return 0;
}
@@ -988,7 +1059,7 @@ static int show_system_task_call(ivl_statement_t net)
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
vec[vecs] = draw_eval_expr(expr);
vec[vecs] = draw_eval_expr(expr, 0);
vecs++;
}
@@ -1071,6 +1142,10 @@ static int show_system_task_call(ivl_statement_t net)
fprintf(vvp_out, ";\n");
/* VPI calls can manipulate anything, so clear the expression
lookahead table after the call. */
clear_expression_lookaside();
return 0;
}
@@ -1205,6 +1280,7 @@ int draw_process(ivl_process_t net, void*x)
/* 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);
clear_expression_lookaside();
/* Draw the contents of the thread. */
rc += show_statement(stmt, scope);
@@ -1239,6 +1315,7 @@ int draw_task_definition(ivl_scope_t scope)
ivl_statement_t def = ivl_scope_def(scope);
fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope)));
clear_expression_lookaside();
assert(def);
rc += show_statement(def, scope);
@@ -1255,6 +1332,7 @@ int draw_func_definition(ivl_scope_t scope)
ivl_statement_t def = ivl_scope_def(scope);
fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope)));
clear_expression_lookaside();
assert(def);
rc += show_statement(def, scope);
@@ -1267,6 +1345,24 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.71 2002/09/27 20:24:42 steve
* Allow expression lookaside map to spam statements.
*
* Revision 1.70 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
* Revision 1.69 2002/09/24 04:20:32 steve
* Allow results in register bits 47 in certain cases.
*
* Revision 1.68 2002/09/13 03:12:50 steve
* Optimize ==1 when in context where x vs z doesnt matter.
*
* Revision 1.67 2002/09/01 00:19:35 steve
* Watch for x indices in l-value of non-blocking assignments.
*
* Revision 1.66 2002/08/31 03:48:50 steve
* Fix reverse bit ordered bit select in continuous assignment.
*
* Revision 1.65 2002/08/27 05:39:57 steve
* Fix l-value indexing of memories and vectors so that
* an unknown (x) index causes so cell to be addresses.
@@ -1343,99 +1439,5 @@ int draw_func_definition(ivl_scope_t scope)
*
* Revision 1.44 2001/09/01 00:58:16 steve
* dead comments.
*
* Revision 1.43 2001/08/26 23:00:13 steve
* Generate code for l-value bit selects.
*
* Revision 1.42 2001/08/25 23:50:03 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.41 2001/08/16 03:45:17 steve
* statement ends after while loop labels.
*
* Revision 1.40 2001/07/28 01:18:07 steve
* Evaluate part selects when passed to system tasks.
*
* Revision 1.39 2001/07/19 04:55:06 steve
* Support calculated delays in vvp.tgt.
*
* Revision 1.38 2001/06/29 02:41:05 steve
* Handle null parameters to system tasks.
*
* Revision 1.37 2001/06/23 00:30:42 steve
* Handle short inputs to tasks. (Stephan Boettcher)
*
* Revision 1.36 2001/06/18 03:10:34 steve
* 1. Logic with more than 4 inputs
* 2. Id and name mangling
* 3. A memory leak in draw_net_in_scope()
* (Stephan Boettcher)
*
* Revision 1.35 2001/05/24 04:31:00 steve
* Attach noops to case labels.
*
* Revision 1.34 2001/05/17 04:37:02 steve
* Behavioral ternary operators for vvp.
*
* Revision 1.33 2001/05/10 00:26:53 steve
* VVP support for memories in expressions,
* including general support for thread bit
* vectors as system task parameters.
* (Stephan Boettcher)
*
* Revision 1.32 2001/05/08 23:59:33 steve
* Add ivl and vvp.tgt support for memories in
* expressions and l-values. (Stephan Boettcher)
*
* Revision 1.31 2001/05/03 04:55:28 steve
* Generate null statements for conditional labels.
*
* Revision 1.30 2001/04/21 03:26:23 steve
* Right shift by constant.
*
* Revision 1.29 2001/04/21 00:55:46 steve
* Generate code for disable.
*
* Revision 1.28 2001/04/18 05:12:03 steve
* Use the new %fork syntax.
*
* Revision 1.27 2001/04/15 02:58:11 steve
* vvp support for <= with internal delay.
*
* Revision 1.26 2001/04/06 02:28:03 steve
* Generate vvp code for functions with ports.
*
* Revision 1.25 2001/04/05 03:20:58 steve
* Generate vvp code for the repeat statement.
*
* Revision 1.24 2001/04/04 04:50:35 steve
* Support forever loops in the tgt-vvp target.
*
* Revision 1.23 2001/04/04 04:28:41 steve
* Fix broken look scanning down bits of number.
*
* Revision 1.22 2001/04/04 04:14:09 steve
* emit vpi parameters values as vectors.
*
* Revision 1.21 2001/04/03 04:50:37 steve
* Support non-blocking assignments.
*
* Revision 1.20 2001/04/02 04:09:20 steve
* thread bit allocation leak in assign.
*
* Revision 1.19 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.18 2001/04/02 00:27:53 steve
* Scopes and numbers as vpi_call parameters.
*
* Revision 1.17 2001/04/01 06:49:04 steve
* Generate code for while statements.
*/
+114 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.77 2002/08/12 01:35:04 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.80 2002/10/23 04:39:35 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -330,6 +330,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
lpm = ivl_nexus_ptr_lpm(nptr);
if (lpm) switch (ivl_lpm_type(lpm)) {
case IVL_LPM_FF:
case IVL_LPM_MUX:
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
if (ivl_lpm_q(lpm, idx) == nex) {
@@ -1264,6 +1265,105 @@ static void draw_lpm_eq(ivl_lpm_t net)
}
}
/*
* primitive FD (q, clk, ce, d);
* output q;
* reg q;
* input clk, ce, d;
* table
* // clk ce d r s q q+
* r 1 0 0 0 : ? : 0;
* r 1 1 0 0 : ? : 1;
* f 1 ? 0 0 : ? : -;
* ? 1 ? 0 0 : ? : -;
* * 0 ? 0 0 : ? : -;
* ? ? ? 1 ? : ? : 0;
* ? ? ? 0 1 : ? : 1;
* endtable
* endprimitive
*/
static void draw_lpm_ff(ivl_lpm_t net)
{
ivl_expr_t aset_expr = 0;
const char*aset_bits = 0;
unsigned width, idx;
width = ivl_lpm_width(net);
/* Q C CE D RS --> Q+ */
fprintf(vvp_out, "L_%s/def .udp/sequ \"DFF\", 5, 2,"
" \"?" "r" "1" "0" "00" "0\","
" \"?" "r" "1" "1" "00" "1\","
" \"?" "r" "1" "x" "00" "x\","
" \"0" "r" "x" "0" "00" "0\","
" \"1" "r" "x" "1" "00" "1\","
" \"?" "*" "0" "?" "00" "-\","
" \"?" "_" "?" "?" "00" "-\","
" \"?" "?" "?" "?" "01" "1\","
" \"?" "?" "?" "?" "1?" "0\","
" \"?" "?" "1" "?" "00" "-\","
" \"?" "?" "?" "?" "00" "-\""
";\n", vvp_mangle_id(ivl_lpm_name(net)));
aset_expr = ivl_lpm_aset_value(net);
if (aset_expr) {
assert(ivl_expr_width(aset_expr) == width);
aset_bits = ivl_expr_bits(aset_expr);
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t tmp;
fprintf(vvp_out, "L_%s/%u .udp ",
vvp_mangle_id(ivl_lpm_name(net)), idx);
fprintf(vvp_out, "L_%s/def, ", vvp_mangle_id(ivl_lpm_name(net)));
tmp = ivl_lpm_clk(net);
draw_input_from_net(tmp);
tmp = ivl_lpm_enable(net);
fprintf(vvp_out, ", ");
if (tmp)
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<1>");
tmp = ivl_lpm_data(net, idx);
assert(tmp);
fprintf(vvp_out, ", ");
draw_input_from_net(tmp);
/* Connect reset input. This may be the Aclr input, or
an Aset to zero. */
fprintf(vvp_out, ", ");
tmp = ivl_lpm_async_clr(net);
if (tmp) {
draw_input_from_net(tmp);
} else {
tmp = ivl_lpm_async_set(net);
if (aset_bits && (aset_bits[idx] == '0'))
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<0>");
}
/* Connect set input */
fprintf(vvp_out, ", ");
tmp = ivl_lpm_async_set(net);
if (aset_bits && (aset_bits[idx] != '1'))
tmp = 0;
if (tmp)
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<0>");
fprintf(vvp_out, ";\n");
}
}
static void draw_lpm_shiftl(ivl_lpm_t net)
{
unsigned idx, width, selects;
@@ -1373,6 +1473,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_eq(net);
return;
case IVL_LPM_FF:
draw_lpm_ff(net);
return;
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
draw_lpm_cmp(net);
@@ -1488,6 +1592,15 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.80 2002/10/23 04:39:35 steve
* draw lpm ff with aset_expr taken into account.
*
* Revision 1.79 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.78 2002/09/17 05:37:45 steve
* Generate vvp code for structural flip-flops.
*
* Revision 1.77 2002/08/12 01:35:04 steve
* conditional ident string using autoconfig.
*
+3 -5
View File
@@ -1,10 +1,10 @@
Summary: Icarus Verilog
Name: verilog
Version: 0.6.20020817
Version: 0.6.20021027
Release: 0
Copyright: GPL
Group: Applications/Engineering
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20020817.tar.gz
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20021027.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-20020817
%setup -n verilog-20021027
%build
./configure --prefix=/usr
@@ -49,10 +49,8 @@ make prefix=$RPM_BUILD_ROOT/usr install
%attr(-,root,root) /usr/lib/ivl/fpga.tgt
%attr(-,root,root) /usr/lib/ivl/iverilog.conf
%attr(-,root,root) /usr/lib/libvpi.a
%attr(-,root,root) /usr/lib/libvpip.a
%attr(-,root,root) /usr/lib/libveriuser.a
%attr(-,root,root) /usr/include/ivl_target.h
%attr(-,root,root) /usr/include/vpi_priv.h
%attr(-,root,root) /usr/include/vpi_user.h
%attr(-,root,root) /usr/include/acc_user.h
%attr(-,root,root) /usr/include/veriuser.h
+103 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_display.c,v 1.44 2002/08/24 02:02:44 steve Exp $"
#ident "$Id: sys_display.c,v 1.45 2002/09/06 04:56:28 steve Exp $"
#endif
# include "config.h"
@@ -206,6 +206,91 @@ static void format_time(unsigned mcd, int fsize, const char*value)
vpi_mcd_printf(mcd, "%s", bp);
}
static const char str_char1_table[256] = {
".HS1M222" "W3333333" /* 00 0F */ "L4444444" "44444444" /* 10 1F */
"P5555555" "55555555" /* 20 2F */ "55555555" "55555555" /* 30 3F */
"S6666666" "66666666" /* 40 4F */ "66666666" "66666666" /* 50 5F */
"66666666" "66666666" /* 60 6F */ "66666666" "66666666" /* 70 7F */
"S7777777" "77777777" /* 80 8F */ "77777777" "77777777" /* 90 9F */
"77777777" "77777777" /* A0 AF */ "77777777" "77777777" /* B0 BF */
"77777777" "77777777" /* C0 CF */ "77777777" "77777777" /* D0 DF */
"77777777" "77777777" /* E0 EF */ "77777777" "77777777" /* F0 FF */ };
static const char str_char2_table[256] = {
".im0e010" "e0102010" /* 00 0F */ "a0102010" "30102010" /* 10 1F */
"u0102010" "30102010" /* 20 2F */ "40102010" "30102010" /* 30 3F */
"t0102010" "30102010" /* 40 4F */ "40102010" "30102010" /* 50 5F */
"50102010" "30102010" /* 60 6F */ "40102010" "30102010" /* 70 7F */
"u0102010" "30102010" /* 80 8F */ "40102010" "30102010" /* 90 9F */
"50102010" "30102010" /* A0 AF */ "40102010" "30102010" /* B0 BF */
"60102010" "30102010" /* C0 CF */ "40102010" "30102010" /* D0 DF */
"50102010" "30102010" /* E0 EF */ "40102010" "30102010" /* F0 FF */ };
static void format_strength(unsigned int mcd, s_vpi_value*value)
{
char str[4];
str[0] = '.';
str[1] = '.';
str[2] = '.';
str[3] = 0;
switch (value->value.strength[0].logic) {
case vpi0:
str[0] = str_char1_table[value->value.strength[0].s0];
str[1] = str_char2_table[value->value.strength[0].s0];
str[2] = '0';
break;
case vpi1:
str[0] = str_char1_table[value->value.strength[0].s1];
str[1] = str_char2_table[value->value.strength[0].s1];
str[2] = '1';
break;
case vpiX:
if (value->value.strength[0].s0 == 1) {
str[0] = str_char1_table[value->value.strength[0].s1];
str[1] = str_char2_table[value->value.strength[0].s1];
str[2] = 'H';
} else if (value->value.strength[0].s1 == 1) {
str[0] = str_char1_table[value->value.strength[0].s0];
str[1] = str_char2_table[value->value.strength[0].s0];
str[2] = 'L';
} else if (value->value.strength[0].s1 ==
value->value.strength[0].s0) {
str[0] = str_char1_table[value->value.strength[0].s0];
str[1] = str_char2_table[value->value.strength[0].s0];
str[2] = 'X';
} else {
int ss;
str[0] = '0';
ss = value->value.strength[0].s0;
while (ss > 1) {
str[0] += 1;
ss >>= 1;
}
str[1] = '0';
ss = value->value.strength[0].s1;
while (ss > 1) {
str[1] += 1;
ss >>= 1;
}
str[2] = 'X';
}
break;
case vpiZ:
str[0] = 'H';
str[1] = 'i';
str[2] = 'Z';
break;
default:
assert(0);
}
vpi_mcd_printf(mcd, "%s", str);
}
/*
* If $display discovers a string as a parameter, this function is
* called to process it as a format string. I need the argv handle as
@@ -354,6 +439,14 @@ static int format_str(vpiHandle scope, unsigned int mcd,
cp += 1;
break;
case 'v':
case 'V':
format_char = 'v';
do_arg = 1;
value.format = vpiStrengthVal;
cp += 1;
break;
case '%':
if (fsize != -1 && ffsize != -1) {
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
@@ -364,8 +457,6 @@ static int format_str(vpiHandle scope, unsigned int mcd,
cp += 1;
break;
case 'v':
case 'V':
case 'e':
case 'f':
case 'g':
@@ -477,6 +568,10 @@ static int format_str(vpiHandle scope, unsigned int mcd,
}
break;
case 'v':
format_strength(mcd, &value);
break;
default:
if (fsize > 0)
vpi_mcd_printf(mcd, "%*s", fsize,
@@ -1366,6 +1461,11 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.45 2002/09/06 04:56:28 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
* the bufif devices so that they are logic x.
*
* Revision 1.44 2002/08/24 02:02:44 steve
* Rewire time formatting to handle all cases.
*
+12 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: bufif.cc,v 1.8 2002/08/12 01:35:07 steve Exp $"
#ident "$Id: bufif.cc,v 1.9 2002/09/06 04:56:28 steve Exp $"
#endif
# include "bufif.h"
@@ -25,9 +25,12 @@
# include "schedule.h"
# include "statistics.h"
vvp_bufif_s::vvp_bufif_s(bool en_invert, bool out_invert)
vvp_bufif_s::vvp_bufif_s(bool en_invert, bool out_invert,
unsigned str0, unsigned str1)
: pol_(en_invert? 1 : 0), inv_(out_invert? 1 : 0)
{
odrive0 = str0;
odrive1 = str1;
count_functors_bufif += 1;
}
@@ -41,8 +44,8 @@ void vvp_bufif_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned)
unsigned char out0 = 0x00 | (odrive0<<0) | (odrive0<<4);
unsigned char out1 = 0x88 | (odrive1<<0) | (odrive1<<4);
unsigned char outX = 0x80 | (odrive0<<0) | (odrive1<<4);
unsigned char outH = 0x88 | (0) | (odrive1<<4);
unsigned char outL = 0x00 | (odrive0<<0) | (0);
unsigned char outH = 0x80 | (0) | (odrive1<<4);
unsigned char outL = 0x80 | (odrive0<<0) | (0);
unsigned val;
unsigned str;
@@ -98,6 +101,11 @@ void vvp_bufif_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned)
/*
* $Log: bufif.cc,v $
* Revision 1.9 2002/09/06 04:56:28 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
* the bufif devices so that they are logic x.
*
* Revision 1.8 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
+8 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: bufif.h,v 1.5 2002/08/12 01:35:07 steve Exp $"
#ident "$Id: bufif.h,v 1.6 2002/09/06 04:56:29 steve Exp $"
#endif
# include "functor.h"
@@ -27,7 +27,8 @@
class vvp_bufif_s : public functor_s {
public:
vvp_bufif_s(bool en_invert, bool out_invert);
vvp_bufif_s(bool en_invert, bool out_invert,
unsigned str0, unsigned str1);
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
@@ -38,6 +39,11 @@ class vvp_bufif_s : public functor_s {
/*
* $Log: bufif.h,v $
* Revision 1.6 2002/09/06 04:56:29 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
* the bufif devices so that they are logic x.
*
* Revision 1.5 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
+9 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: codes.h,v 1.49 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: codes.h,v 1.51 2002/09/18 04:29:55 steve Exp $"
#endif
@@ -79,8 +79,10 @@ extern bool of_MOD(vthread_t thr, vvp_code_t code);
extern bool of_MOV(vthread_t thr, vvp_code_t code);
extern bool of_MUL(vthread_t thr, vvp_code_t code);
extern bool of_MULI(vthread_t thr, vvp_code_t code);
extern bool of_NAND(vthread_t thr, vvp_code_t code);
extern bool of_NANDR(vthread_t thr, vvp_code_t code);
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
extern bool of_NOR(vthread_t thr, vvp_code_t code);
extern bool of_NORR(vthread_t thr, vvp_code_t code);
extern bool of_OR(vthread_t thr, vvp_code_t code);
extern bool of_ORR(vthread_t thr, vvp_code_t code);
@@ -155,6 +157,12 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
/*
* $Log: codes.h,v $
* Revision 1.51 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.50 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.49 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
+47 -7
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.140 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: compile.cc,v 1.143 2002/09/18 04:29:55 steve Exp $"
#endif
# include "arith.h"
@@ -124,8 +124,10 @@ const static struct opcode_table_s opcode_table[] = {
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@@ -462,6 +464,40 @@ void code_label_lookup(struct vvp_code_s *code, char *label)
resolv_submit(res);
}
/*
* Lookup memories.
*/
struct memory_resolv_list_s: public resolv_list_s {
struct vvp_code_s *code;
char *label;
virtual bool resolve(bool mes);
};
bool memory_resolv_list_s::resolve(bool mes)
{
code->mem = memory_find(label);
if (code->mem != 0) {
free(label);
return true;
}
if (mes)
fprintf(stderr, "Memory unresolved: %s\n", label);
return false;
}
static void compile_mem_lookup(struct vvp_code_s *code, char *label)
{
struct memory_resolv_list_s *res
= new struct memory_resolv_list_s;
res->code = code;
res->label = label;
resolv_submit(res);
}
/*
* When parsing is otherwise complete, this function is called to do
* the final stuff. Clean up deferred linking here.
@@ -1252,12 +1288,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
code->mem = memory_find(opa->argv[idx].symb.text);
if (code->mem == 0) {
yyerror("memory undefined");
}
free(opa->argv[idx].symb.text);
compile_mem_lookup(code, opa->argv[idx].symb.text);
break;
case OA_VPI_PTR:
@@ -1449,6 +1480,15 @@ void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
/*
* $Log: compile.cc,v $
* Revision 1.143 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.142 2002/09/18 02:55:18 steve
* Allow forward references of memories.
*
* Revision 1.141 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.140 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
+43 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_tt.c,v 1.13 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: draw_tt.c,v 1.14 2002/08/29 03:04:01 steve Exp $"
#endif
# include <stdio.h>
@@ -284,6 +284,44 @@ static void draw_NMOS(void)
printf("};\n");
}
static void draw_MUXX(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_MUXX[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 (i3 == 0)
val = 3;
else if (i3 == 2)
val = 2;
else if (i3 == 3)
val = 2;
else if (i2 >= 2) {
val = 2;
} else if (i2 == 0)
val = i0;
else
val = i1;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
static void draw_MUXZ(void)
{
unsigned i0, i1, i2, i3;
@@ -628,6 +666,7 @@ main()
draw_BUFZ();
draw_PMOS();
draw_NMOS();
draw_MUXX();
draw_MUXZ();
draw_EEQ();
draw_NAND();
@@ -643,6 +682,9 @@ main()
/*
* $Log: draw_tt.c,v $
* Revision 1.14 2002/08/29 03:04:01 steve
* Generate x out for x select on wide muxes.
*
* Revision 1.13 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+16 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.cc,v 1.10 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: logic.cc,v 1.12 2002/09/06 04:56:29 steve Exp $"
#endif
# include "logic.h"
@@ -92,10 +92,10 @@ void compile_functor(char*label, char*type,
obj = new table_functor_s(ft_BUF, ostr0, ostr1);
} else if (strcmp(type, "BUFIF0") == 0) {
obj = new vvp_bufif_s(true,false);
obj = new vvp_bufif_s(true,false, ostr0, ostr1);
} else if (strcmp(type, "BUFIF1") == 0) {
obj = new vvp_bufif_s(false,false);
obj = new vvp_bufif_s(false,false, ostr0, ostr1);
} else if (strcmp(type, "BUFZ") == 0) {
obj = new table_functor_s(ft_BUFZ, ostr0, ostr1);
@@ -112,6 +112,9 @@ void compile_functor(char*label, char*type,
} else if (strcmp(type, "RNMOS") == 0) {
obj = new vvp_rnmos_s;
} else if (strcmp(type, "MUXX") == 0) {
obj = new table_functor_s(ft_MUXX);
} else if (strcmp(type, "MUXZ") == 0) {
obj = new table_functor_s(ft_MUXZ);
@@ -128,10 +131,10 @@ void compile_functor(char*label, char*type,
obj = new table_functor_s(ft_NOT, ostr0, ostr1);
} else if (strcmp(type, "NOTIF0") == 0) {
obj = new vvp_bufif_s(true,true);
obj = new vvp_bufif_s(true,true, ostr0, ostr1);
} else if (strcmp(type, "NOTIF1") == 0) {
obj = new vvp_bufif_s(false,true);
obj = new vvp_bufif_s(false,true, ostr0, ostr1);
} else if (strcmp(type, "XNOR") == 0) {
obj = new table_functor_s(ft_XNOR, ostr0, ostr1);
@@ -164,6 +167,14 @@ void compile_functor(char*label, char*type,
/*
* $Log: logic.cc,v $
* Revision 1.12 2002/09/06 04:56:29 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
* the bufif devices so that they are logic x.
*
* Revision 1.11 2002/08/29 03:04:01 steve
* Generate x out for x select on wide muxes.
*
* Revision 1.10 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.h,v 1.5 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: logic.h,v 1.6 2002/08/29 03:04:01 steve Exp $"
#endif
# include "functor.h"
@@ -51,6 +51,7 @@ extern const unsigned char ft_BUFIF1[];
extern const unsigned char ft_BUFZ[];
extern const unsigned char ft_PMOS[];
extern const unsigned char ft_NMOS[];
extern const unsigned char ft_MUXX[];
extern const unsigned char ft_MUXZ[];
extern const unsigned char ft_EEQ[];
extern const unsigned char ft_NAND[];
@@ -63,6 +64,9 @@ extern const unsigned char ft_var[];
/*
* $Log: logic.h,v $
* Revision 1.6 2002/08/29 03:04:01 steve
* Generate x out for x select on wide muxes.
*
* Revision 1.5 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.30 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: main.cc,v 1.31 2002/09/18 03:34:07 steve Exp $"
#endif
# include "config.h"
@@ -245,7 +245,7 @@ int main(int argc, char*argv[])
fprintf(stderr, " %8lu resolv\n", count_functors_resolv);
fprintf(stderr, " %8lu variable\n", count_functors_var);
fprintf(stderr, " ... %8lu opcodes (%lu bytes)\n",
count_opcodes, size_opcodes);
count_opcodes, (unsigned long)size_opcodes);
fprintf(stderr, " ... %8lu nets\n", count_vpi_nets);
fprintf(stderr, " ... %8lu memories\n", count_vpi_memories);
fprintf(stderr, " ... %8lu scopes\n", count_vpi_scopes);
@@ -280,6 +280,9 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.31 2002/09/18 03:34:07 steve
* printf size warning.
*
* Revision 1.30 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+10 -4
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: memory.cc,v 1.18 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: memory.cc,v 1.19 2002/09/17 00:42:22 steve Exp $"
#endif
#include "memory.h"
@@ -130,12 +130,15 @@ char *memory_name(vvp_memory_t mem)
// Compilation
static symbol_table_t memory_table;
static symbol_table_t memory_table = 0;
vvp_memory_t memory_find(char *label)
{
symbol_value_t v = sym_get_value(memory_table, label);
return (vvp_memory_t)v.ptr;
if (memory_table == 0)
return 0;
symbol_value_t v = sym_get_value(memory_table, label);
return (vvp_memory_t)v.ptr;
}
vvp_memory_t memory_create(char *label)
@@ -507,6 +510,9 @@ void schedule_memory(vvp_memory_t mem, unsigned idx,
/*
* $Log: memory.cc,v $
* Revision 1.19 2002/09/17 00:42:22 steve
* Proper initialization of the memories table.
*
* Revision 1.18 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+25 -1
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams ([email protected])
*
* $Id: opcodes.txt,v 1.40 2002/08/28 18:38:07 steve Exp $
* $Id: opcodes.txt,v 1.42 2002/09/18 04:29:55 steve Exp $
*/
@@ -359,6 +359,30 @@ This instruction is the same as %mul, but the second operand is an
immediate value that is padded to the width of the result.
* %nand <dst>, <src>, <wid>
Perform the bitwise NAND of the two vectors, and store the result in
the left vector. Each bit is calculated independent of other bits. NAND
means the following:
0 and ? --> 1
? and 0 --> 1
1 and 1 --> 0
otherwise x
* %nor <dst>, <src>, <wid>
Perform the bitwise nor of the vectors. Each bit in the <dst> is
combined with the corresponding bit in the source, according to the
truth table:
1 nor ? --> 0
? nor 1 --> 0
0 nor 0 --> 1
otherwise x
* %nor/r <dst>, <src>, <wid>
The %nor/r instruction is a reduction nor. That is, the <src> is a
+7 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: resolv.cc,v 1.14 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: resolv.cc,v 1.15 2002/09/06 04:56:29 steve Exp $"
#endif
# include "resolv.h"
@@ -35,6 +35,7 @@
# define STREN1(v) ( ((v)&0x80)? ((v)&0xf0) : (0x70 - ((v)&0xf0)) )
# define STREN0(v) ( ((v)&0x08)? ((v)&0x0f) : (0x07 - ((v)&0x0f)) )
# include <iostream>
static unsigned blend(unsigned a, unsigned b)
{
if (a == HiZ)
@@ -203,6 +204,11 @@ void resolv_functor_s::debug_print(vvp_ipoint_t fnc)
/*
* $Log: resolv.cc,v $
* Revision 1.15 2002/09/06 04:56:29 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
* the bufif devices so that they are logic x.
*
* Revision 1.14 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+82 -47
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_callback.cc,v 1.23 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: vpi_callback.cc,v 1.25 2002/09/20 02:42:11 steve Exp $"
#endif
/*
@@ -249,6 +249,8 @@ static void make_sync_run(vvp_gen_event_t obj, unsigned char)
cur->cb_data.time->type = vpiSimTime;
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
assert(cur->cb_data.cb_rtn != 0);
assert(vpi_mode_flag == VPI_MODE_NONE);
vpi_mode_flag = cb->sync_flag? VPI_MODE_ROSYNC : VPI_MODE_RWSYNC;
(cur->cb_data.cb_rtn)(&cur->cb_data);
@@ -296,6 +298,37 @@ static struct __vpiCallback* make_sync(p_cb_data data, bool readonly_flag)
return obj;
}
static struct __vpiCallback* make_afterdelay(p_cb_data data)
{
struct __vpiCallback*obj = new_vpi_callback();
obj->cb_data = *data;
assert(data->time);
obj->cb_time = *(data->time);
obj->cb_data.time = &obj->cb_time;
obj->next = 0;
struct sync_cb*cb = new sync_cb;
cb->sync_flag = false;
cb->run = &make_sync_run;
cb->handle = obj;
obj->cb_sync = cb;
switch (obj->cb_time.type) {
case vpiSimTime: {
vvp_time64_t tv = vpip_timestruct_to_time(&obj->cb_time);
schedule_generic(cb, 0, tv);
break;
}
default:
assert(0);
break;
}
return obj;
}
/*
* The following functions are the used for pre and post simulation
* callbacks.
@@ -394,6 +427,10 @@ vpiHandle vpi_register_cb(p_cb_data data)
obj = make_sync(data, false);
break;
case cbAfterDelay:
obj = make_afterdelay(data);
break;
case cbEndOfCompile:
case cbStartOfSimulation:
case cbEndOfSimulation:
@@ -410,14 +447,19 @@ vpiHandle vpi_register_cb(p_cb_data data)
return obj? &obj->base : 0;
}
/*
* Removing a callback doesn't really delete it right away. Instead,
* it clears the reference to the user callback function. This causes
* the callback to quietly reap itself.
*/
int vpi_remove_cb(vpiHandle ref)
{
assert(ref);
assert(ref->vpi_type);
assert(ref->vpi_type->type_code == vpiCallback);
fprintf(stderr, "vpi error: vpi_remove_cb not supported\n");
struct __vpiCallback*obj = (struct __vpiCallback*)ref;
obj->cb_data.cb_rtn = 0;
return 0;
}
@@ -427,6 +469,7 @@ void callback_execute(struct __vpiCallback*cur)
const vpi_mode_t save_mode = vpi_mode_flag;
vpi_mode_flag = VPI_MODE_RWSYNC;
assert(cur->cb_data.cb_rtn);
cur->cb_data.time->type = vpiSimTime;
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
(cur->cb_data.cb_rtn)(&cur->cb_data);
@@ -443,23 +486,43 @@ void callback_execute(struct __vpiCallback*cur)
void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
{
struct __vpiCallback *next = cb_handle;
struct __vpiCallback *prev = 0;
while (next) {
struct __vpiCallback * cur = next;
next = cur->next;
if (cur->cb_data.value) {
switch (cur->cb_data.value->format) {
case vpiScalarVal:
cur->cb_data.value->value.scalar = val;
break;
case vpiSuppressVal:
break;
default:
fprintf(stderr, "vpi_callback: value format %d not supported\n", cur->cb_data.value->format);
if (cur->cb_data.cb_rtn != 0) {
if (cur->cb_data.value) {
switch (cur->cb_data.value->format) {
case vpiScalarVal:
cur->cb_data.value->value.scalar = val;
break;
case vpiSuppressVal:
break;
default:
fprintf(stderr, "vpi_callback: value "
"format %d not supported\n",
cur->cb_data.value->format);
}
}
callback_execute(cur);
prev = cur;
} else if (prev == 0) {
cb_handle = next;
cur->next = 0;
vpi_free_object(&cur->base);
} else {
assert(prev->next == cur);
prev->next = next;
cur->next = 0;
vpi_free_object(&cur->base);
}
callback_execute(cur);
}
}
@@ -467,6 +530,12 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
/*
* $Log: vpi_callback.cc,v $
* Revision 1.25 2002/09/20 02:42:11 steve
* Add support for cbAfterDelay.
*
* Revision 1.24 2002/09/07 04:54:51 steve
* Implement vpi_remove_cb for cbValueChange.
*
* Revision 1.23 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
@@ -510,39 +579,5 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
*
* Revision 1.11 2002/04/06 20:25:45 steve
* cbValueChange automatically replays.
*
* Revision 1.10 2001/11/06 03:07:22 steve
* Code rearrange. (Stephan Boettcher)
*
* Revision 1.9 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.8 2001/10/25 04:19:53 steve
* VPI support for callback to return values.
*
* Revision 1.7 2001/10/12 03:00:09 steve
* M42 implementation of mode 2 (Stephan Boettcher)
*
* Revision 1.6 2001/09/15 18:27:05 steve
* Make configure detect malloc.h
*
* Revision 1.5 2001/08/08 01:05:06 steve
* Initial implementation of vvp_fvectors.
* (Stephan Boettcher)
*
* Revision 1.4 2001/07/13 03:02:34 steve
* Rewire signal callback support for fast lookup. (Stephan Boettcher)
*
* Revision 1.3 2001/07/11 02:27:21 steve
* Add support for REadOnlySync and monitors.
*
* Revision 1.2 2001/06/21 23:05:08 steve
* Some documentation of callback behavior.
*
* Revision 1.1 2001/06/21 22:54:12 steve
* Support cbValueChange callbacks.
*
*/
+17 -5
View File
@@ -27,7 +27,7 @@
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_memory.cc,v 1.18 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_memory.cc,v 1.20 2002/09/12 15:13:07 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -109,20 +109,23 @@ static char* memory_get_str(int code, vpiHandle ref)
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
char *bn = vpi_get_str(vpiFullName, &rfp->scope->base);
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->scope->base));
char *nm = memory_name(rfp->mem);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 2, RBUF_STR);
switch (code) {
case vpiFullName:
sprintf(rbuf, "%s.%s", bn, nm);
free(bn);
return rbuf;
case vpiName:
strcpy(rbuf, nm);
free(bn);
return rbuf;
}
free(bn);
return 0;
}
@@ -344,23 +347,26 @@ static char* memory_word_get_str(int code, vpiHandle ref)
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
char *bn = vpi_get_str(vpiFullName, &rfp->mem->scope->base);
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->mem->scope->base));
char *nm = memory_name(rfp->mem->mem);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 10 + 4, RBUF_STR);
switch (code) {
case vpiFullName:
sprintf(rbuf, "%s.%s[%d]", bn, nm, rfp->index.value);
free(bn);
return rbuf;
break;
case vpiName: {
sprintf(rbuf, "%s[%d]", nm, rfp->index.value);
free(bn);
return rbuf;
break;
}
}
free(bn);
return 0;
}
@@ -580,6 +586,12 @@ vpiHandle vpip_make_memory(vvp_memory_t mem)
/*
* $Log: vpi_memory.cc,v $
* Revision 1.20 2002/09/12 15:13:07 steve
* Account for buffer overrun in memory word names.
*
* Revision 1.19 2002/09/11 16:06:57 steve
* Fix wrecked rbuf in vpi_get_str of signals and memories.
*
* Revision 1.18 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+64 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_signal.cc,v 1.46 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.49 2002/09/11 16:06:57 steve Exp $"
#endif
/*
@@ -62,10 +62,11 @@ char *need_result_buf(unsigned cnt, vpi_rbuf_t type)
if (result_buf_size[type] == 0) {
result_buf[type] = (char*)malloc(cnt);
result_buf_size[type] = cnt;
} else if (result_buf_size[type] < cnt) {
result_buf[type] = (char*)realloc(result_buf[type], cnt);
result_buf_size[type] = cnt;
}
result_buf_size[type] = cnt;
return result_buf[type];
}
@@ -109,22 +110,25 @@ static char* signal_get_str(int code, vpiHandle ref)
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
char *bn = vpi_get_str(vpiFullName, &rfp->scope->base);
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->scope->base));
char *nm = (char*)rfp->name;
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 2, RBUF_STR);
switch (code) {
case vpiFullName:
sprintf(rbuf, "%s.%s", bn, nm);
free(bn);
return rbuf;
case vpiName:
strcpy(rbuf, nm);
free(bn);
return rbuf;
}
free(bn);
return 0;
}
@@ -378,6 +382,51 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
break;
}
case vpiStrengthVal: {
s_vpi_strengthval*op = (s_vpi_strengthval*)
need_result_buf(wid * sizeof(s_vpi_strengthval),
RBUF_VAL);
vp->value.strength = op;
/* Convert the internal strength values of each
functor in the vector to a PLI2.0 version. */
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
functor_t fp = functor_index(fptr);
unsigned str = fp->get_ostr();
unsigned s0 = 1 << (str&0x07);
unsigned s1 = 1 << ((str>>4) & 0x07);
switch (fp->get()) {
case 0:
op[idx].logic = vpi0;
op[idx].s0 = s0|s1;
op[idx].s1 = 0;
break;
case 1:
op[idx].logic = vpi1;
op[idx].s0 = 0;
op[idx].s1 = s0|s1;
break;
case 2:
op[idx].logic = vpiX;
op[idx].s0 = s0;
op[idx].s1 = s1;
break;
case 3:
op[idx].logic = vpiZ;
op[idx].s0 = vpiHiZ;
op[idx].s1 = vpiHiZ;
break;
default:
assert(0);
}
}
break;
}
default:
fprintf(stderr, "vvp internal error: signal_get_value: "
"value type %u not implemented.\n", vp->format);
@@ -673,6 +722,17 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.49 2002/09/11 16:06:57 steve
* Fix wrecked rbuf in vpi_get_str of signals and memories.
*
* Revision 1.48 2002/09/10 02:27:11 steve
* Actually set strength pointer when getting strength val.
*
* Revision 1.47 2002/09/06 04:56:29 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
* the bufif devices so that they are logic x.
*
* Revision 1.46 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+158 -40
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vthread.cc,v 1.84 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: vthread.cc,v 1.89 2002/09/21 23:47:30 steve Exp $"
#endif
# include "vthread.h"
@@ -72,7 +72,7 @@
*
* A --> C(zombie) --> X --> B
*
* If A then executes 2 %joins, it will read C and X (when it ends)
* If A then executes 2 %joins, it will reap C and X (when it ends)
* leaving B in purgatory. What's worse, A will block on the schedules
* of X and C instead of C and B, possibly creating incorrect timing.
*
@@ -103,6 +103,7 @@ struct vthread_s {
unsigned i_have_ended :1;
unsigned waiting_for_event :1;
unsigned is_scheduled :1;
unsigned fork_count :8;
/* This points to the sole child of the thread. */
struct vthread_s*child;
/* This points to my parent, if I have one. */
@@ -213,7 +214,7 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
thr->nbits = 4 * (CPU_WORD_BITS/2);
thr->child = 0;
thr->parent = 0;
thr->wait_next = 0;
thr->wait_next = 0;
/* If the target scope never held a thread, then create a
header cell for it. This is a stub to make circular lists
@@ -241,6 +242,7 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
thr->i_have_ended = 0;
thr->waiting_for_event = 0;
thr->is_scheduled = 0;
thr->fork_count = 0;
thr_put_bit(thr, 0, 0);
thr_put_bit(thr, 1, 1);
@@ -256,15 +258,17 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
*/
static void vthread_reap(vthread_t thr)
{
assert(thr->wait_next == 0);
free(thr->bits);
thr->bits = 0;
if (thr->child)
if (thr->child) {
assert(thr->child->parent == thr);
thr->child->parent = thr->parent;
if (thr->parent)
}
if (thr->parent) {
assert(thr->parent->child == thr);
thr->parent->child = thr->child;
}
thr->child = 0;
thr->parent = 0;
@@ -277,8 +281,11 @@ static void vthread_reap(vthread_t thr)
/* If this thread is not scheduled, then is it safe to delete
it now. Otherwise, let the schedule event (which will
execute the thread at of_ZOMBIE) delete the object. */
if (thr->is_scheduled == 0)
if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) {
assert(thr->fork_count == 0);
assert(thr->wait_next == 0);
delete thr;
}
}
void vthread_mark_scheduled(vthread_t thr)
@@ -752,14 +759,63 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
return false;
}
static bool do_disable(vthread_t thr, vthread_t match)
{
bool flag = false;
/* Pull the target thread out of its scope. */
thr->scope_next->scope_prev = thr->scope_prev;
thr->scope_prev->scope_next = thr->scope_next;
/* Turn the thread off by setting is program counter to
zero and setting an OFF bit. */
thr->pc = 0;
thr->i_have_ended = 1;
/* Turn off all the children of the thread. Simulate a %join
for as many times as needed to clear the results of all the
%forks that this thread has done. */
while (thr->fork_count > 0) {
vthread_t tmp = thr->child;
assert(tmp);
assert(tmp->parent == thr);
tmp->schedule_parent_on_end = 0;
if (do_disable(tmp, match))
flag = true;
thr->fork_count -= 1;
vthread_reap(tmp);
}
if (thr->schedule_parent_on_end) {
/* If a parent is waiting in a %join, wake it up. */
assert(thr->parent);
assert(thr->parent->fork_count > 0);
thr->parent->fork_count -= 1;
schedule_vthread(thr->parent, 0, true);
vthread_reap(thr);
} else if (thr->parent) {
/* If the parent is yet to %join me, let its %join
do the reaping. */
//assert(tmp->is_scheduled == 0);
} else {
/* No parent at all. Goodby. */
vthread_reap(thr);
}
return flag || (thr == match);
}
/*
* Implement the %disable instruction by scanning the target scope for
* all the target threads. Kill the target threads and wake up a
* parent that is attempting a %join.
*
* XXXX BUG BUG!
* The scheduler probably still has a pointer to me, and this reaping
* will destroy this object. The result: dangling pointer.
*/
bool of_DISABLE(vthread_t thr, vvp_code_t cp)
{
@@ -774,38 +830,14 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
while (head->scope_next != head) {
vthread_t tmp = head->scope_next;
/* Pull the target thread out of the scope. */
tmp->scope_next->scope_prev = tmp->scope_prev;
tmp->scope_prev->scope_next = tmp->scope_next;
/* XXXX I don't support disabling threads with children. */
assert(tmp->child == 0);
/* XXXX Don't know how to disable waiting threads. */
assert(tmp->waiting_for_event == 0);
/* If I am disabling myself, that remember that fact so
that I can finish this statement differently. */
if (tmp == thr)
disabled_myself_flag = true;
tmp->pc = 0;
tmp->i_have_ended = 1;
if (tmp->schedule_parent_on_end) {
/* If a parent is waiting in a %join, wake it up. */
assert(tmp->parent);
schedule_vthread(tmp->parent, 0, true);
vthread_reap(tmp);
} else if (tmp->parent) {
/* If the parent is yet to %join me, let its %join
do the reaping. */
//assert(tmp->is_scheduled == 0);
} else {
/* No parent at all. Goodby. */
vthread_reap(tmp);
}
if (do_disable(tmp, thr))
disabled_myself_flag = true;
}
return ! disabled_myself_flag;
@@ -1146,7 +1178,7 @@ bool of_DIV_S(vthread_t thr, vvp_code_t cp)
bool of_END(vthread_t thr, vvp_code_t)
{
assert(! thr->waiting_for_event);
assert( thr->fork_count == 0 );
thr->i_have_ended = 1;
thr->pc = 0;
@@ -1155,6 +1187,9 @@ bool of_END(vthread_t thr, vvp_code_t)
%join for the parent. */
if (thr->schedule_parent_on_end) {
assert(thr->parent);
assert(thr->parent->fork_count > 0);
thr->parent->fork_count -= 1;
schedule_vthread(thr->parent, 0, true);
vthread_reap(thr);
return false;
@@ -1196,6 +1231,9 @@ bool of_FORK(vthread_t thr, vvp_code_t cp)
assert(child->child->parent == thr);
child->child->parent = child;
}
thr->fork_count += 1;
schedule_vthread(child, 0, true);
return true;
}
@@ -1327,8 +1365,12 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
assert(thr->child);
assert(thr->child->parent == thr);
assert(thr->fork_count > 0);
/* If the child has already ended, reap it now. */
if (thr->child->i_have_ended) {
thr->fork_count -= 1;
vthread_reap(thr->child);
return true;
}
@@ -1815,6 +1857,37 @@ bool of_MULI(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_NAND(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb == 0) || (rb == 0)) {
thr_put_bit(thr, idx1, 1);
} else if ((lb == 1) && (rb == 1)) {
thr_put_bit(thr, idx1, 0);
} else {
thr_put_bit(thr, idx1, 2);
}
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
return true;
}
bool of_NOOP(vthread_t thr, vvp_code_t cp)
{
return true;
@@ -1992,6 +2065,36 @@ bool of_OR(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_NOR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb == 1) || (rb == 1)) {
thr_put_bit(thr, idx1, 0);
} else if ((lb == 0) && (rb == 0)) {
thr_put_bit(thr, idx1, 1);
} else {
thr_put_bit(thr, idx1, 2);
}
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
return true;
}
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
bool of_SET(vthread_t thr, vvp_code_t cp)
@@ -2319,6 +2422,21 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.89 2002/09/21 23:47:30 steve
* Remove some now useless asserts.
*
* Revision 1.88 2002/09/21 04:55:00 steve
* Fix disable in arbitrary fork/join situations.
*
* Revision 1.87 2002/09/20 03:59:34 steve
* disable threads with children.
*
* Revision 1.86 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.85 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.84 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*