mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-22 22:06:47 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c66d319d9c | ||
|
|
ae27165ffe | ||
|
|
32f1ca6f8b | ||
|
|
9ce2806710 | ||
|
|
3d4593d4d5 | ||
|
|
df5ae54ec7 | ||
|
|
fbee1b424d | ||
|
|
555017b525 | ||
|
|
1e170ee005 | ||
|
|
43501809b1 | ||
|
|
c0c67a101a | ||
|
|
1eb714e097 | ||
|
|
54a8e12856 | ||
|
|
6203f05ef9 | ||
|
|
703ad04067 | ||
|
|
778e96330d | ||
|
|
e3eb89fb12 | ||
|
|
166621bcb3 | ||
|
|
879a5a4cbe | ||
|
|
9faabfe995 | ||
|
|
6f23fa61ac | ||
|
|
30b6cf7821 | ||
|
|
6258011210 | ||
|
|
7557a46382 | ||
|
|
a0a91f358c | ||
|
|
0128286966 | ||
|
|
acd5e86e04 | ||
|
|
ab94b0a636 | ||
|
|
de6d696667 | ||
|
|
63946c4cfb | ||
|
|
475b603d15 | ||
|
|
096956cda9 | ||
|
|
3d3116d48b | ||
|
|
616360d751 | ||
|
|
7a5c30d297 | ||
|
|
9c5ab36a8b | ||
|
|
466656b167 | ||
|
|
5d6567cb02 | ||
|
|
c44c123ef5 | ||
|
|
4ecbf56e2b | ||
|
|
ed9a2c4b3f | ||
|
|
90751b9250 | ||
|
|
7d8011669d | ||
|
|
eb81062d85 | ||
|
|
8fbacc966e | ||
|
|
75801a12e3 | ||
|
|
9f1ce170e6 | ||
|
|
327c8826f4 | ||
|
|
fb0383d2bd | ||
|
|
28725d0d74 | ||
|
|
dac99b9374 | ||
|
|
1573477caf | ||
|
|
70a7513781 | ||
|
|
0277035496 | ||
|
|
33f462fdf6 | ||
|
|
639b9f346f | ||
|
|
447fee6f43 | ||
|
|
c9212a9a09 | ||
|
|
ea21fab379 | ||
|
|
4d090b64bd | ||
|
|
7e1e44e87a | ||
|
|
0a2a9dcd94 | ||
|
|
c9b4b66af2 | ||
|
|
7b6678b2a1 | ||
|
|
e79f62c5fa | ||
|
|
60046cc790 |
+2
-2
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user