Rework of internals to carry vectors through nexus instead

of single bits. Make the ivl, tgt-vvp and vvp initial changes
 down this path.
This commit is contained in:
steve 2004-12-11 02:31:25 +00:00
parent 6854660e18
commit 65e9b6be12
68 changed files with 3433 additions and 3153 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.170 2004/12/11 02:31:25 steve Exp $"
#
#
SHELL = /bin/sh
@ -104,8 +104,8 @@ distclean: clean
do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $"
#ident "$Id: Statement.h,v 1.41 2004/12/11 02:31:25 steve Exp $"
#endif
# include <string>
@ -36,6 +36,7 @@ class Design;
class NetAssign_;
class NetCAssign;
class NetDeassign;
class NetForce;
class NetScope;
/*
@ -345,7 +346,7 @@ class PForce : public Statement {
explicit PForce(PExpr*l, PExpr*r);
~PForce();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@ -456,6 +457,11 @@ class PWhile : public Statement {
/*
* $Log: Statement.h,v $
* Revision 1.41 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.40 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*

115
cprop.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $"
#ident "$Id: cprop.cc,v 1.48 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -55,86 +55,6 @@ void cprop_functor::signal(Design*des, NetNet*obj)
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
{
// For now, only additions are handled.
if (obj->attribute(perm_string::literal("LPM_Direction")) != verinum("ADD"))
return;
// If the low bit on the A side is 0, then eliminate it from
// the adder, and pass the B side directly to the
// result. Don't reduce the adder smaller then a 1-bit
// adder. These will be eliminated later.
while ((obj->width() > 1)
&& obj->pin_DataA(0).nexus()->drivers_constant()
&& (obj->pin_DataA(0).nexus()->driven_value() == verinum::V0)) {
NetAddSub*tmp = 0;
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
//connect(tmp->pin_Clock(), obj->pin_Clock());
//connect(tmp->pin_Cin(), obj->pin_Cin());
connect(tmp->pin_Cout(), obj->pin_Cout());
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
}
connect(obj->pin_Result(0), obj->pin_DataB(0));
delete obj;
des->add_node(tmp);
obj = tmp;
count += 1;
}
// Now do the same thing on the B side.
while ((obj->width() > 1)
&& obj->pin_DataB(0).nexus()->drivers_constant()
&& (obj->pin_DataB(0).nexus()->driven_value() == verinum::V0)) {
NetAddSub*tmp = 0;
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
//connect(tmp->pin_Clock(), obj->pin_Clock());
//connect(tmp->pin_Cin(), obj->pin_Cin());
connect(tmp->pin_Cout(), obj->pin_Cout());
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
}
connect(obj->pin_Result(0), obj->pin_DataA(0));
delete obj;
des->add_node(tmp);
obj = tmp;
count += 1;
}
// If the adder is only 1 bit wide, then replace it with the
// simple logic gate.
if (obj->width() == 1) {
NetLogic*tmp;
if (obj->pin_Cout().is_linked()) {
tmp = new NetLogic(obj->scope(),
obj->scope()->local_symbol(),
3, NetLogic::AND);
connect(tmp->pin(0), obj->pin_Cout());
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
des->add_node(tmp);
}
tmp = new NetLogic(obj->scope(), obj->name(), 3, NetLogic::XOR);
connect(tmp->pin(0), obj->pin_Result(0));
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
delete obj;
des->add_node(tmp);
count += 1;
return;
}
}
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
@ -248,7 +168,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
with a simple XOR gate. */
if (top == 1) {
NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
NetLogic::XNOR);
NetLogic::XNOR, 1);
connect(tmp->pin(0), obj->pin_AEB());
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
@ -449,12 +369,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::AND:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
break;
case NetLogic::NAND:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
break;
default:
assert(0);
@ -480,7 +400,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type());
obj->type(), 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
@ -597,12 +517,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::OR:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
break;
case NetLogic::NOR:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
break;
default:
assert(0);
@ -627,7 +547,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type());
obj->type(), 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
@ -766,11 +686,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
else
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
@ -795,11 +715,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF);
NetLogic::BUF, 1);
else
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT);
NetLogic::NOT, 1);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
@ -821,7 +741,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type());
obj->type(), 1);
des->add_node(tmp);
tmp->pin(0).drive0(obj->pin(0).drive0());
tmp->pin(0).drive1(obj->pin(0).drive1());
@ -873,7 +793,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF1);
3, NetLogic::BUFIF1, 1);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
@ -906,7 +826,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF0);
3, NetLogic::BUFIF0, 1);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
@ -1038,6 +958,11 @@ void cprop(Design*des)
/*
* $Log: cprop.cc,v $
* Revision 1.48 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.149 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: design_dump.cc,v 1.150 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -96,8 +96,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope()->name();
o << " #(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") init=";
o << " #(" << rise_time() << "," << fall_time() << ","
<< decay_time() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count()
<< " init=";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << pin(idx-1).get_init();
@ -189,18 +191,13 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
void NetAddSub::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCAssign::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
<< name() << endl;
dump_node_pins(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
@ -223,12 +220,6 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetForce::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << endl;
dump_node_pins(o, ind+4);
}
void NetMult::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
@ -249,7 +240,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "NetBUFZ: " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ")" << endl;
decay_time() << ") width=" << width() << endl;
dump_node_pins(o, ind+4);
}
@ -261,8 +252,8 @@ void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
void NetConst::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant ";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << setw(ind) << "" << "constant " << width_ << "'b";
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
o << value_[idx-1];
o << ": " << name() << endl;
dump_node_pins(o, ind+4);
@ -353,6 +344,13 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetPartSelect: "
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetRamDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
@ -557,8 +555,9 @@ void NetCase::dump(ostream&o, unsigned ind) const
void NetCAssign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "cassign " << lval_->name() << " = "
<< name() << ";" << endl;
o << setw(ind) << "" << "cassign ";
dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
}
void NetCondit::dump(ostream&o, unsigned ind) const
@ -578,8 +577,9 @@ void NetCondit::dump(ostream&o, unsigned ind) const
void NetDeassign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "deassign " << lval_->name() << "; "
<< "/* " << get_line() << " */" << endl;
o << setw(ind) << "" << "deassign ";
dump_lval(o);
o << "; /* " << get_line() << " */" << endl;
}
void NetDisable::dump(ostream&o, unsigned ind) const
@ -632,8 +632,9 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << " = "
<< name() << ";" << endl;
o << setw(ind) << "" << "force ";
dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
}
void NetForever::dump(ostream&o, unsigned ind) const
@ -677,12 +678,9 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
void NetRelease::dump(ostream&o, unsigned ind) const
{
if (lval_)
o << setw(ind) << "" << "release " << lval_->name() << "; "
<< "/* " << get_line() << " */" << endl;
else
o << setw(ind) << "" << "release (null); "
<< "/* " << get_line() << " */" << endl;
o << setw(ind) << "" << "release ";
dump_lval(o);
o << "; /* " << get_line() << " */" << endl;
}
void NetRepeat::dump(ostream&o, unsigned ind) const
@ -995,7 +993,7 @@ void NetESignal::dump(ostream&o) const
{
if (has_sign())
o << "+";
o << name() << "[" << msi_<<":"<<lsi_ << "]";
o << name() << "[" << msi()<<":"<<lsi() << "]";
}
void NetEBitSel::dump(ostream&o) const
@ -1089,6 +1087,11 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.150 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.149 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.18 2004/06/17 16:06:18 steve Exp $"
#ident "$Id: dup_expr.cc,v 1.19 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -87,7 +87,7 @@ NetESFunc* NetESFunc::dup_expr() const
NetESignal* NetESignal::dup_expr() const
{
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
NetESignal*tmp = new NetESignal(net_);
assert(tmp);
tmp->expr_width(expr_width());
return tmp;
@ -143,6 +143,11 @@ NetEVariable* NetEVariable::dup_expr() const
/*
* $Log: dup_expr.cc,v $
* Revision 1.19 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/06/17 16:06:18 steve
* Help system function signedness survive elaboration.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.91 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: elab_expr.cc,v 1.92 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -699,10 +699,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
delete msn;
return 0;
}
#if 0
NetESignal*tmp = new NetESignal(net,
net->sb_to_idx(msv),
net->sb_to_idx(lsv));
#else
NetESignal*tmp = new NetESignal(net);
cerr << get_line() << ": internal error: I forgot "
"how to elaborate part selects." << endl;
#endif
tmp->set_line(*this);
return tmp;
@ -735,7 +740,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp;
}
#if 0
NetESignal*tmp = new NetESignal(net, idx, idx);
#else
NetESignal*tmp = new NetESignal(net);
cerr << get_line() << ": internal error: I forgot "
"how to elaborate constant bit selects." << endl;
#endif
tmp->set_line(*this);
return tmp;
@ -1005,6 +1016,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/*
* $Log: elab_expr.cc,v $
* Revision 1.92 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.91 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.30 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -283,7 +283,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->pin_count()) {
if ((wid + loff) > reg->vector_width()) {
cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
@ -293,8 +293,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
lv = new NetAssign_(reg);
lv->set_part(loff, wid);
assert(moff < reg->pin_count());
}
@ -352,6 +350,11 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.30 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.29 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -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.138 2004/10/04 03:09:38 steve Exp $"
#ident "$Id: elab_net.cc,v 1.139 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -195,14 +195,13 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
/* The owidth is the output width of the lpm_add_sub
device. If the desired width is greater then the width of
the operands, then widen the adder and let code below pad
the operands. If this is an adder, we can take advantage of
the carry bit. */
the operands. */
unsigned owidth = width;
switch (op_) {
case '+':
if (lwidth > owidth) {
owidth = lwidth;
width = lwidth-1;
width = lwidth;
}
break;
case '-':
@ -228,18 +227,21 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, owidth);
osig->local_flag(true);
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate NetAddSub "
<< "width=" << width << " lwidth=" << lwidth
<< endl;
}
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), width);
// Connect the adder to the various parts.
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(lsig->pin(idx), adder->pin_DataA(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(rsig->pin(idx), adder->pin_DataB(idx));
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(osig->pin(idx), adder->pin_Result(idx));
connect(lsig->pin(0), adder->pin_DataA());
connect(rsig->pin(0), adder->pin_DataB());
connect(osig->pin(0), adder->pin_Result());
#ifdef XXXX
if (owidth > width)
connect(osig->pin(width), adder->pin_Cout());
#endif
NetNode*gate = adder;
gate->rise_time(rise);
gate->fall_time(fall);
@ -311,7 +313,7 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, gtype);
3, gtype, 1);
connect(gate->pin(1), lsig->pin(idx));
connect(gate->pin(2), rsig->pin(idx));
connect(gate->pin(0), osig->pin(idx));
@ -394,12 +396,12 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
NetLogic*ones_gate = 0;
if (zeros > 0)
zero_gate = new NetLogic(scope,
scope->local_symbol(), zeros + 1,
(op_code == 'n') ? NetLogic::OR : NetLogic::NOR);
scope->local_symbol(), zeros + 1,
(op_code == 'n') ? NetLogic::OR : NetLogic::NOR, 1);
if (ones > 0)
ones_gate = new NetLogic(scope,
scope->local_symbol(), ones + 1,
(op_code == 'n') ? NetLogic::NAND : NetLogic::AND);
scope->local_symbol(), ones + 1,
(op_code == 'n') ? NetLogic::NAND : NetLogic::AND, 1);
unsigned zidx = 0;
unsigned oidx = 0;
@ -426,7 +428,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
connect(and_sig->pin(1), ones_gate->pin(0));
NetLogic*and_gate = new NetLogic(scope,
scope->local_symbol(), 3,
(op_code == 'n') ? NetLogic::OR : NetLogic::AND);
(op_code == 'n') ? NetLogic::OR : NetLogic::AND, 1);
connect(and_gate->pin(0), osig->pin(0));
connect(and_gate->pin(1), and_sig->pin(0));
connect(and_gate->pin(2), and_sig->pin(1));
@ -625,7 +627,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
gate = new NetLogic(scope, scope->local_symbol(),
1+dwidth,
(op_ == 'E')? NetLogic::AND : NetLogic::NAND);
(op_ == 'E')? NetLogic::AND : NetLogic::NAND, 1);
connect(gate->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
NetCaseCmp*cmp = new NetCaseCmp(scope,
@ -659,7 +661,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
single XNOR gate. This is easy and direct. */
if (dwidth == 1) {
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR);
3, NetLogic::XNOR, 1);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
@ -693,7 +695,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
single XOR gate. This is easy and direct. */
if (dwidth == 1) {
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR);
3, NetLogic::XOR, 1);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
@ -899,11 +901,11 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
switch (op_) {
case 'a':
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::AND);
3, NetLogic::AND, 1);
break;
case 'o':
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::OR);
3, NetLogic::OR, 1);
break;
default:
assert(0);
@ -915,7 +917,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
// The first OR gate returns 1 if the left value is true...
if (lsig->pin_count() > 1) {
gate_t = new NetLogic(scope, scope->local_symbol(),
1+lsig->pin_count(), NetLogic::OR);
1+lsig->pin_count(), NetLogic::OR, 1);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(gate_t->pin(idx+1), lsig->pin(idx));
@ -937,7 +939,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
// The second OR gate returns 1 if the right value is true...
if (rsig->pin_count() > 1) {
gate_t = new NetLogic(scope, scope->local_symbol(),
1+rsig->pin_count(), NetLogic::OR);
1+rsig->pin_count(), NetLogic::OR, 1);
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(gate_t->pin(idx+1), rsig->pin(idx));
connect(gate->pin(2), gate_t->pin(0));
@ -1586,7 +1588,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
signal for the part select to be correct. */
if (! (sig->sb_is_valid(mbit) && sig->sb_is_valid(lbit))) {
cerr << get_line() << ": error: bit/part select ["
<< mval->as_long() << ":" << lval->as_long()
<< mbit << ":" << lbit
<< "] out of range for " << sig->name() << endl;
des->errors += 1;
return sig;
@ -1619,7 +1621,19 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
unsigned part_count = midx-lidx+1;
NetSubnet*tmp = new NetSubnet(sig, lidx, part_count);
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate part select "
<< sig->name() << "["<<mbit<<":"<<lbit<<"]" << endl;
}
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count);
ps->set_line(*sig);
des->add_node(ps);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, part_count-1, 0);
tmp->local_flag(true);
connect(tmp->pin(0), ps->pin(0));
sig = tmp;
@ -1632,15 +1646,35 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << ": error: index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
long mbit = mval->as_long();
/* Check that the part select is valid. Both ends of the
constant part select must be within the range of the
signal for the part select to be correct. */
if (! sig->sb_is_valid(mbit)) {
cerr << get_line() << ": error: bit/part select ["
<< mbit
<< "] out of range for " << sig->name() << endl;
des->errors += 1;
idx = 0;
return sig;
}
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
unsigned midx = sig->sb_to_idx(mbit);
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate part select "
<< sig->name() << "["<<mval->as_long()<<"]" << endl;
}
NetPartSelect*ps = new NetPartSelect(sig, midx, 1);
ps->set_line(*sig);
des->add_node(ps);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1, 0);
tmp->local_flag(true);
connect(tmp->pin(0), ps->pin(0));
sig = tmp;
}
@ -1698,7 +1732,10 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
/*
* The concatenation is also OK an an l-value. This method elaborates
* it as a structural l-value.
* it as a structural l-value. The return values is the *input* net of
* the l-value, which may feed via part selects to the final
* destination. The caller can connect gate outputs to this signal to
* make the l-value connections.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
@ -1706,7 +1743,7 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
assert(scope);
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned width = 0;
unsigned errors = 0;
if (repeat_) {
@ -1718,6 +1755,12 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
/* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate subexpression "
<< idx << " of " << nets.count() << " l-values: "
<< *parms_[idx] << endl;
}
if (parms_[idx] == 0) {
cerr << get_line() << ": error: Empty expressions "
<< "not allowed in concatenations." << endl;
@ -1730,7 +1773,7 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
width += nets[idx]->vector_width();
}
/* If any of the sub expressions failed to elaborate, then
@ -1745,19 +1788,33 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list. */
concat operator from most significant to least significant,
which is the order they are given in the concat list. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pins);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
NetNet::IMPLICIT, width);
if (debug_elaborate) {
cerr << get_line() << ": debug: Generating part selects "
<< "to connect input l-value to subexpressions."
<< endl;
}
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
unsigned wid = nets[idx]->vector_width();
unsigned off = width - wid;
NetPartSelect*ps = new NetPartSelect(osig, off, wid);
des->add_node(ps);
connect(ps->pin(1), osig->pin(0));
connect(ps->pin(0), nets[idx]->pin(0));
assert(wid <= width);
width -= wid;
}
assert(width == 0);
osig->local_flag(true);
return osig;
}
@ -2046,18 +2103,15 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
break;
}
verinum num(top_v, net->pin_count());
verinum num(top_v, net->vector_width());
unsigned idx;
for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1)
num.set(idx, value_->get(idx));
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
num);
for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
tmp->pin(idx).drive0(drive0);
tmp->pin(idx).drive1(drive1);
connect(net->pin(idx), tmp->pin(idx));
}
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
tmp->pin(0).drive0(drive0);
tmp->pin(0).drive1(drive1);
connect(net->pin(0), tmp->pin(0));
des->add_node(tmp);
return net;
@ -2073,8 +2127,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
net->set_signed(value_->has_sign());
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
*value_);
for (unsigned idx = 0 ; idx < value_->len() ; idx += 1)
connect(net->pin(idx), tmp->pin(idx));
connect(net->pin(0), tmp->pin(0));
des->add_node(tmp);
return net;
@ -2116,8 +2169,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
NetNet::IMPLICIT, width);
net->local_flag(true);
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(net->pin(idx), tmp->pin(idx));
connect(net->pin(0), tmp->pin(0));
des->add_node(tmp);
return net;
@ -2224,7 +2276,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
if (expr_sig->pin_count() > 1) {
NetLogic*log = new NetLogic(scope, scope->local_symbol(),
expr_sig->pin_count()+1,
NetLogic::OR);
NetLogic::OR, 1);
for (unsigned idx = 0; idx < expr_sig->pin_count(); idx += 1)
connect(log->pin(idx+1), expr_sig->pin(idx));
@ -2284,7 +2336,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
NetNet::WIRE, dwidth);
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol());
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(), 1);
tmpz->rise_time(rise);
tmpz->fall_time(fall);
tmpz->decay_time(decay);
@ -2388,7 +2440,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
sig->local_flag(true);
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) {
gate = new NetLogic(scope, scope->local_symbol(),
2, NetLogic::NOT);
2, NetLogic::NOT, 1);
connect(gate->pin(1), sub_sig->pin(idx));
connect(gate->pin(0), sig->pin(idx));
des->add_node(gate);
@ -2427,7 +2479,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
case 1:
gate = new NetLogic(scope, scope->local_symbol(),
2, NetLogic::BUF);
2, NetLogic::BUF, 1);
connect(gate->pin(0), sig->pin(0));
connect(gate->pin(1), sub_sig->pin(0));
des->add_node(gate);
@ -2438,7 +2490,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
case 2:
gate = new NetLogic(scope, scope->local_symbol(),
2, NetLogic::BUF);
2, NetLogic::BUF, 1);
connect(gate->pin(0), sig->pin(0));
connect(gate->pin(1), sub_sig->pin(0));
des->add_node(gate);
@ -2447,7 +2499,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
gate->decay_time(decay);
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR);
3, NetLogic::XOR, 1);
connect(gate->pin(0), sig->pin(1));
connect(gate->pin(1), sub_sig->pin(0));
connect(gate->pin(2), sub_sig->pin(1));
@ -2464,11 +2516,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
des->add_node(sub);
for (unsigned idx = 0 ; idx < sig->pin_count(); idx += 1)
connect(sig->pin(idx), sub->pin_Result(idx));
for (unsigned idx = 0; idx < sub_sig->pin_count(); idx += 1)
connect(sub_sig->pin(idx), sub->pin_DataB(idx));
connect(sig->pin(0), sub->pin_Result());
connect(sub_sig->pin(0), sub->pin_DataB());
verinum tmp_num (verinum::V0, sub->width(), true);
NetConst*tmp_con = new NetConst(scope,
@ -2481,10 +2530,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
sub_sig->pin_count());
tmp_sig->local_flag(true);
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
connect(tmp_sig->pin(idx), sub->pin_DataA(idx));
connect(tmp_sig->pin(idx), tmp_con->pin(idx));
}
connect(tmp_sig->pin(0), sub->pin_DataA());
connect(tmp_sig->pin(0), tmp_con->pin(0));
break;
}
break;
@ -2497,7 +2544,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
sig->local_flag(true);
gate = new NetLogic(scope, scope->local_symbol(),
1+sub_sig->pin_count(), gtype);
1+sub_sig->pin_count(), gtype, 1);
connect(gate->pin(0), sig->pin(0));
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
connect(gate->pin(idx+1), sub_sig->pin(idx));
@ -2513,6 +2560,11 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.139 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.138 2004/10/04 03:09:38 steve
* Fix excessive error message.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_sig.cc,v 1.36 2004/09/27 22:34:10 steve Exp $"
#ident "$Id: elab_sig.cc,v 1.37 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -610,6 +610,12 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
} else {
perm_string name = lex_strings.make(hname_.peek_tail_name());
if (debug_elaborate) {
cerr << get_line() << ": debug: Create signal "
<< name << "["<<msb<<":"<<lsb<<"]"
<< " in scope " << scope->name() << endl;
}
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
sig->set_line(*this);
sig->port_type(port_type_);
@ -623,6 +629,11 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
/*
* $Log: elab_sig.cc,v $
* Revision 1.37 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.36 2004/09/27 22:34:10 steve
* Cleanup and factoring of autoconf.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.308 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: elaborate.cc,v 1.309 2004/12/11 02:31:25 steve Exp $"
#endif
# include "config.h"
@ -91,6 +91,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
return;
}
assert(lval->pin_count() == 1);
if (debug_elaborate) {
cerr << lval->get_line() << ": debug: Elaborated l-value "
<< "width=" << lval->vector_width() << endl;
}
/* Handle the special case that the rval is simply an
identifier. Get the rval as a NetNet, then use NetBUFZ
@ -98,7 +104,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
direct drivers. This is how I attach strengths to the
assignment operation. */
if (const PEIdent*id = dynamic_cast<const PEIdent*>(pin(1))) {
NetNet*rid = id->elaborate_net(des, scope, lval->pin_count(),
NetNet*rid = id->elaborate_net(des, scope, lval->vector_width(),
0, 0, 0, Link::STRONG,
Link::STRONG);
if (rid == 0) {
@ -107,7 +113,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
}
assert(rid);
assert(rid->pin_count() == 1);
/* If the right hand net is the same type as the left
side net (i.e., WIRE/WIRE) then it is enough to just
@ -118,20 +124,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
is not as wide as the l-value by padding with a
constant-0. */
unsigned cnt = lval->pin_count();
if (rid->pin_count() < cnt)
unsigned cnt = lval->vector_width();
if (rid->vector_width() < cnt)
cnt = rid->pin_count();
bool need_driver_flag = false;
/* If the device is linked to itself, a driver is
needed. Should I print a warning here? */
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
if (lval->pin(idx) .is_linked (rid->pin(idx))) {
need_driver_flag = true;
break;
}
}
if (lval->pin(0) .is_linked (rid->pin(0)))
need_driver_flag = true;
/* If the nets are different type (i.e., reg vs. tri) then
a driver is needed. */
@ -145,16 +147,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
/* If there is a strength to be carried, then I need a
driver to carry that strength. */
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
if (rid->pin(idx).drive0() != drive0) {
need_driver_flag = true;
break;
}
if (rid->pin(idx).drive1() != drive1) {
need_driver_flag = true;
break;
}
}
if (rid->pin(0).drive0() != drive0)
need_driver_flag = true;
if (rid->pin(0).drive1() != drive1)
need_driver_flag = true;
if (! need_driver_flag) {
/* Don't need a driver, presumably because the
@ -162,11 +160,10 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
hook things up. If the r-value is too narrow
for the l-value, then sign extend it or zero
extend it, whichever makes sense. */
unsigned idx;
for (idx = 0 ; idx < cnt; idx += 1)
connect(lval->pin(idx), rid->pin(idx));
connect(lval->pin(0), rid->pin(0));
if (cnt < lval->pin_count()) {
#if 0
if (lval->get_signed() && rid->get_signed()) {
for (idx = cnt
; idx < lval->pin_count()
@ -184,45 +181,28 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
; idx += 1)
connect(lval->pin(idx), tmp->pin(idx-cnt));
}
#else
cerr << get_line() << ": internal error: "
<< "Forgot how to handle mismatched widths."
<< endl;
#endif
}
} else {
/* Do need a driver. Use BUFZ objects to carry the
strength and delays. */
unsigned idx;
for (idx = 0 ; idx < cnt ; idx += 1) {
NetBUFZ*dev = new NetBUFZ(scope,scope->local_symbol());
connect(lval->pin(idx), dev->pin(0));
connect(rid->pin(idx), dev->pin(1));
dev->rise_time(rise_time);
dev->fall_time(fall_time);
dev->decay_time(decay_time);
dev->pin(0).drive0(drive0);
dev->pin(0).drive1(drive1);
des->add_node(dev);
}
if (cnt < lval->pin_count()) {
if (lval->get_signed() && rid->get_signed()) {
for (idx = cnt
; idx < lval->pin_count()
; idx += 1)
connect(lval->pin(idx), lval->pin(cnt-1));
NetBUFZ*dev = new NetBUFZ(scope, scope->local_symbol(),
rid->vector_width());
connect(lval->pin(0), dev->pin(0));
connect(rid->pin(0), dev->pin(1));
dev->rise_time(rise_time);
dev->fall_time(fall_time);
dev->decay_time(decay_time);
dev->pin(0).drive0(drive0);
dev->pin(0).drive1(drive1);
des->add_node(dev);
} else {
NetConst*dev = new NetConst(scope,
scope->local_symbol(),
verinum::V0);
des->add_node(dev);
dev->pin(0).drive0(drive0);
dev->pin(0).drive1(drive1);
for (idx = cnt
; idx < lval->pin_count()
; idx += 1)
connect(lval->pin(idx), dev->pin(0));
}
}
}
return;
@ -232,7 +212,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
which are going to be attached to the last gate before the
generated NetNet. */
NetNet*rval = pin(1)->elaborate_net(des, scope,
lval->pin_count(),
lval->vector_width(),
rise_time, fall_time, decay_time,
drive0, drive1);
if (rval == 0) {
@ -243,17 +223,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
}
assert(lval && rval);
assert(rval->pin_count() == 1);
/* If the r-value insists on being smaller then the l-value
(perhaps it is explicitly sized) the pad it out to be the
right width so that something is connected to all the bits
of the l-value. */
if (lval->pin_count() > rval->pin_count())
rval = pad_to_width(des, rval, lval->pin_count());
if (lval->vector_width() > rval->vector_width())
rval = pad_to_width(des, rval, lval->vector_width());
for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1)
connect(lval->pin(idx), rval->pin(idx));
connect(lval->pin(0), rval->pin(0));
if (lval->local_flag())
delete lval;
@ -355,75 +334,75 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
switch (type()) {
case AND:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::AND);
NetLogic::AND, 1);
break;
case BUF:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUF);
NetLogic::BUF, 1);
break;
case BUFIF0:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUFIF0);
NetLogic::BUFIF0, 1);
break;
case BUFIF1:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUFIF1);
NetLogic::BUFIF1, 1);
break;
case NAND:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NAND);
NetLogic::NAND, 1);
break;
case NMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NMOS);
NetLogic::NMOS, 1);
break;
case NOR:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOR);
NetLogic::NOR, 1);
break;
case NOT:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOT);
NetLogic::NOT, 1);
break;
case NOTIF0:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOTIF0);
NetLogic::NOTIF0, 1);
break;
case NOTIF1:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOTIF1);
NetLogic::NOTIF1, 1);
break;
case OR:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::OR);
NetLogic::OR, 1);
break;
case RNMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::RNMOS);
NetLogic::RNMOS, 1);
break;
case RPMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::RPMOS);
NetLogic::RPMOS, 1);
break;
case PMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PMOS);
NetLogic::PMOS, 1);
break;
case PULLDOWN:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PULLDOWN);
NetLogic::PULLDOWN, 1);
break;
case PULLUP:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PULLUP);
NetLogic::PULLUP, 1);
break;
case XNOR:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XNOR);
NetLogic::XNOR, 1);
break;
case XOR:
cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XOR);
NetLogic::XOR, 1);
break;
default:
cerr << get_line() << ": internal error: unhandled "
@ -1712,29 +1691,36 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
return block;
}
/*
* Elaborate a proceedural continuous assign. This really looks very
* much like other prodeedural assignments, at this point, but there
* is no delay to worry about. The code generator will take care of
* the differences between continuous assign and normal assignments.
*/
NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
{
NetCAssign*dev = 0;
assert(scope);
NetNet*lval = lval_->elaborate_anet(des, scope);
NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0)
return 0;
NetNet*rval = expr_->elaborate_net(des, scope, lval->pin_count(),
0, 0, 0);
if (rval == 0)
NetExpr*rexp = elab_and_eval(des, scope, expr_);
if (rexp == 0)
return 0;
if (rval->pin_count() < lval->pin_count())
rval = pad_to_width(des, rval, lval->pin_count());
dev = new NetCAssign(lval, rexp);
if (debug_elaborate) {
cerr << get_line() << ": debug: ELaborate cassign,"
<< " lval width=" << lval->lwidth()
<< " rval width=" << rexp->expr_width()
<< " rval=" << *rexp
<< endl;
}
NetCAssign* dev = new NetCAssign(scope, scope->local_symbol(), lval);
dev->set_line(*this);
des->add_node(dev);
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1)
connect(dev->pin(idx), rval->pin(idx));
return dev;
}
@ -1742,7 +1728,7 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetNet*lval = lval_->elaborate_anet(des, scope);
NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0)
return 0;
@ -2225,28 +2211,30 @@ NetProc* PForever::elaborate(Design*des, NetScope*scope) const
return proc;
}
NetProc* PForce::elaborate(Design*des, NetScope*scope) const
NetForce* PForce::elaborate(Design*des, NetScope*scope) const
{
NetForce*dev = 0;
assert(scope);
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0);
NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0)
return 0;
NetNet*rval = expr_->elaborate_net(des, scope, lval->pin_count(),
0, 0, 0);
if (rval == 0)
NetExpr*rexp = elab_and_eval(des, scope, expr_);
if (rexp == 0)
return 0;
if (rval->pin_count() < lval->pin_count())
rval = pad_to_width(des, rval, lval->pin_count());
dev = new NetForce(lval, rexp);
NetForce* dev = new NetForce(scope, scope->local_symbol(), lval);
des->add_node(dev);
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1)
connect(dev->pin(idx), rval->pin(idx));
if (debug_elaborate) {
cerr << get_line() << ": debug: ELaborate force,"
<< " lval width=" << lval->lwidth()
<< " rval width=" << rexp->expr_width()
<< " rval=" << *rexp
<< endl;
}
dev->set_line(*this);
return dev;
}
@ -2398,7 +2386,7 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0);
NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0)
return 0;
@ -2769,96 +2757,10 @@ Design* elaborate(list<perm_string>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.308 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
* Revision 1.309 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.307 2004/09/05 21:07:26 steve
* Support degenerat wait statements.
*
* Revision 1.306 2004/09/05 17:44:41 steve
* Add support for module instance arrays.
*
* Revision 1.305 2004/06/30 15:32:02 steve
* Propagate source line number in synthetic delay statements.
*
* Revision 1.304 2004/06/20 15:59:06 steve
* Only pad the width of vector r-values.
*
* Revision 1.303 2004/06/13 04:56:54 steve
* Add support for the default_nettype directive.
*
* Revision 1.302 2004/05/31 23:34:37 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
* speed and more type support.
*
* Revision 1.301 2004/05/25 03:42:58 steve
* Handle wait with constant-false expression.
*
* Revision 1.300 2004/03/08 00:47:44 steve
* primitive ports can bind bi name.
*
* Revision 1.299 2004/03/08 00:10:29 steve
* Verilog2001 new style port declartions for primitives.
*
* Revision 1.298 2004/03/07 20:04:10 steve
* MOre thorough use of elab_and_eval function.
*
* Revision 1.297 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.296 2004/02/18 17:11:55 steve
* Use perm_strings for named langiage items.
*
* Revision 1.295 2004/01/21 04:35:03 steve
* Get rid of useless warning.
*
* Revision 1.294 2004/01/13 03:42:49 steve
* Handle wide expressions in wait condition.
*
* Revision 1.293 2003/10/26 04:49:51 steve
* Attach line number information to for loop parts.
*
* Revision 1.292 2003/09/25 00:25:14 steve
* Summary list of missing modules.
*
* Revision 1.291 2003/09/20 06:08:53 steve
* Evaluate nb-assign r-values using elab_and_eval.
*
* Revision 1.290 2003/09/20 06:00:37 steve
* Evaluate gate array index constants using elab_and_eval.
*
* Revision 1.289 2003/09/20 01:05:35 steve
* Obsolete find_symbol and find_event from the Design class.
*
* Revision 1.288 2003/09/13 01:01:51 steve
* Spelling fixes.
*
* Revision 1.287 2003/09/04 20:28:05 steve
* Support time0 resolution of combinational threads.
*
* Revision 1.286 2003/08/28 04:11:17 steve
* Spelling patch.
*
* Revision 1.285 2003/08/05 03:01:58 steve
* Primitive outputs have same limitations as continuous assignment.
*
* Revision 1.284 2003/07/02 04:19:16 steve
* Elide empty begin-end in conditionals.
*
* Revision 1.283 2003/06/21 01:21:43 steve
* Harmless fixup of warnings.
*
* Revision 1.282 2003/06/13 19:10:20 steve
* Handle assign of real to vector.
*
* Revision 1.281 2003/05/19 02:50:58 steve
* Implement the wait statement behaviorally instead of as nets.
*
* Revision 1.280 2003/05/04 20:04:08 steve
* Fix truncation of signed constant in constant addition.
*
* Revision 1.279 2003/04/24 05:25:55 steve
* Include port name in port assignment error message.
*/

150
emit.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: emit.cc,v 1.77 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: emit.cc,v 1.78 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@ -63,12 +63,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
return true;
}
bool NetCAssign::emit_node(struct target_t*tgt) const
{
tgt->net_cassign(this);
return true;
}
bool NetCLShift::emit_node(struct target_t*tgt) const
{
tgt->lpm_clshift(this);
@ -98,12 +92,6 @@ bool NetFF::emit_node(struct target_t*tgt) const
return true;
}
bool NetForce::emit_node(struct target_t*tgt) const
{
tgt->net_force(this);
return true;
}
bool NetModulo::emit_node(struct target_t*tgt) const
{
tgt->lpm_modulo(this);
@ -122,6 +110,11 @@ bool NetMux::emit_node(struct target_t*tgt) const
return true;
}
bool NetPartSelect::emit_node(struct target_t*tgt) const
{
return tgt->part_select(this);
}
bool NetRamDq::emit_node(struct target_t*tgt) const
{
tgt->lpm_ram_dq(this);
@ -511,6 +504,11 @@ bool emit(const Design*des, const char*type)
/*
* $Log: emit.cc,v $
* Revision 1.78 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.77 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
@ -536,131 +534,5 @@ bool emit(const Design*des, const char*type)
* Revision 1.71 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.70 2002/11/03 20:36:10 steve
* Error message for mising code generator type.
*
* Revision 1.69 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.68 2002/06/05 03:44:25 steve
* Add support for memory words in l-value of
* non-blocking assignments, and remove the special
* NetAssignMem_ and NetAssignMemNB classes.
*
* Revision 1.67 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.66 2002/03/09 02:10:22 steve
* Add the NetUserFunc netlist node.
*
* Revision 1.65 2002/01/28 00:52:41 steve
* Add support for bit select of parameters.
* This leads to a NetESelect node and the
* vvp code generator to support that.
*
* Revision 1.64 2002/01/19 19:02:08 steve
* Pass back target errors processing conditionals.
*
* Revision 1.63 2001/10/19 21:53:24 steve
* Support multiple root modules (Philip Blundell)
*
* Revision 1.62 2001/08/25 23:50:02 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.61 2001/07/27 04:51:44 steve
* Handle part select expressions as variants of
* NetESignal/IVL_EX_SIGNAL objects, instead of
* creating new and useless temporary signals.
*
* Revision 1.60 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.59 2001/04/22 23:09:46 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.58 2001/04/06 02:28:02 steve
* Generate vvp code for functions with ports.
*
* Revision 1.57 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.56 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*
* Revision 1.55 2000/11/04 01:54:01 steve
* Modifications in support of gcc 2.96
*
* Revision 1.54 2000/09/26 01:35:42 steve
* Remove the obsolete NetEIdent class.
*
* Revision 1.53 2000/09/17 21:26:15 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.52 2000/09/02 20:54:20 steve
* Rearrange NetAssign to make NetAssign_ separate.
*
* Revision 1.51 2000/08/14 04:39:56 steve
* add th t-dll functions for net_const, net_bufz and processes.
*
* Revision 1.50 2000/08/09 03:43:45 steve
* Move all file manipulation out of target class.
*
* Revision 1.49 2000/08/08 01:50:42 steve
* target methods need not take a file stream.
*
* Revision 1.48 2000/07/30 18:25:43 steve
* Rearrange task and function elaboration so that the
* NetTaskDef and NetFuncDef functions are created during
* signal enaboration, and carry these objects in the
* NetScope class instead of the extra, useless map in
* the Design class.
*
* Revision 1.47 2000/07/29 16:21:08 steve
* Report code generation errors through proc_delay.
*
* Revision 1.46 2000/07/27 05:13:44 steve
* Support elaboration of disable statements.
*
* Revision 1.45 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
* Revision 1.44 2000/05/04 03:37:58 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.43 2000/05/02 03:13:31 steve
* Move memories to the NetScope object.
*
* Revision 1.42 2000/05/02 00:58:12 steve
* Move signal tables to the NetScope class.
*
* Revision 1.41 2000/04/23 03:45:24 steve
* Add support for the procedural release statement.
*
* Revision 1.40 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.39 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,
*
* Handle named events within the mix of net events
* and edges. As a unified lot they get caught together.
* wait statements are broken into more complex statements
* that include a conditional.
*
* Do not generate NetPEvent or NetNEvent objects in
* elaboration. NetEvent, NetEvWait and NetEvProbe
* take over those functions in the netlist.
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.60 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@ -60,11 +60,9 @@ NetNet* NetEBAdd::synthesize(Design*des)
perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
for (unsigned idx = 0 ; idx < width; idx += 1) {
connect(lsig->pin(idx), adder->pin_DataA(idx));
connect(rsig->pin(idx), adder->pin_DataB(idx));
connect(osig->pin(idx), adder->pin_Result(idx));
}
connect(lsig->pin(0), adder->pin_DataA());
connect(rsig->pin(0), adder->pin_DataB());
connect(osig->pin(0), adder->pin_Result());
des->add_node(adder);
switch (op()) {
@ -136,19 +134,19 @@ NetNet* NetEBBits::synthesize(Design*des)
switch (op()) {
case '&':
gate = new NetLogic(scope, oname, 3, NetLogic::AND);
gate = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
break;
case '|':
gate = new NetLogic(scope, oname, 3, NetLogic::OR);
gate = new NetLogic(scope, oname, 3, NetLogic::OR, 1);
break;
case '^':
gate = new NetLogic(scope, oname, 3, NetLogic::XOR);
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, 1);
break;
case 'O':
gate = new NetLogic(scope, oname, 3, NetLogic::NOR);
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, 1);
break;
case 'X':
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR);
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, 1);
break;
default:
assert(0);
@ -191,12 +189,12 @@ NetNet* NetEBComp::synthesize(Design*des)
case 'e':
case 'E':
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR);
lsig->pin_count()+1, NetLogic::NOR, 1);
break;
case 'n':
case 'N':
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR);
lsig->pin_count()+1, NetLogic::OR, 1);
break;
case '>':
@ -205,11 +203,11 @@ NetNet* NetEBComp::synthesize(Design*des)
happen. */
if (rcon) {
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR);
lsig->pin_count()+1, NetLogic::OR, 1);
} else {
assert(0);
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR);
lsig->pin_count()+1, NetLogic::NOR, 1);
}
break;
@ -217,11 +215,11 @@ NetNet* NetEBComp::synthesize(Design*des)
/* 0 < sig is handled like sig > 0. */
if (! rcon) {
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR);
lsig->pin_count()+1, NetLogic::OR, 1);
} else {
assert(0);
gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR);
lsig->pin_count()+1, NetLogic::NOR, 1);
}
break;
@ -258,7 +256,7 @@ NetNet* NetEBComp::synthesize(Design*des)
operation. Make an XNOR gate instead of a comparator. */
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR);
3, NetLogic::XNOR, 1);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
@ -271,7 +269,7 @@ NetNet* NetEBComp::synthesize(Design*des)
an XOR instead of an XNOR gate. */
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR);
3, NetLogic::XOR, 1);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
@ -449,7 +447,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetLogic*olog = new NetLogic(scope, oname,
lsig->pin_count()+rsig->pin_count()+1,
NetLogic::OR);
NetLogic::OR, 1);
connect(osig->pin(0), olog->pin(0));
@ -471,7 +469,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetLogic*olog;
perm_string oname = scope->local_symbol();
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
connect(osig->pin(0), olog->pin(0));
des->add_node(olog);
@ -669,7 +667,7 @@ NetNet* NetEUBits::synthesize(Design*des)
switch (op()) {
case '~':
gate = new NetLogic(scope, oname, 2, NetLogic::NOT);
gate = new NetLogic(scope, oname, 2, NetLogic::NOT, 1);
break;
default:
assert(0);
@ -702,32 +700,32 @@ NetNet* NetEUReduce::synthesize(Design*des)
case 'N':
case '!':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NOR);
NetLogic::NOR, 1);
break;
case '&':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::AND);
NetLogic::AND, 1);
break;
case '|':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::OR);
NetLogic::OR, 1);
break;
case '^':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XOR);
NetLogic::XOR, 1);
break;
case 'A':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NAND);
NetLogic::NAND, 1);
break;
case 'X':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XNOR);
NetLogic::XNOR, 1);
break;
default:
@ -854,27 +852,16 @@ NetNet* NetETernary::synthesize(Design *des)
*/
NetNet* NetESignal::synthesize(Design*des)
{
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
return net_;
assert(msi_ >= lsi_);
unsigned wid = msi_ - lsi_ + 1;
NetScope*scope = net_->scope();
assert(scope);
perm_string name = scope->local_symbol();
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
tmp->local_flag(true);
for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(tmp->pin(idx), net_->pin(idx+lsi_));
return tmp;
return net_;
}
/*
* $Log: expr_synth.cc,v $
* Revision 1.60 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.59 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*

View File

@ -62,6 +62,7 @@ ivl_logic_udp
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
ivl_lpm_base
ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.126 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: ivl_target.h,v 1.127 2004/12/11 02:31:26 steve Exp $"
#endif
#ifdef __cplusplus
@ -231,6 +231,7 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5,
IVL_LPM_PART = 15, /* part select */
IVL_LPM_SHIFTL = 6,
IVL_LPM_SHIFTR = 7,
IVL_LPM_SUB = 8,
@ -388,13 +389,36 @@ extern int ivl_design_time_precision(ivl_design_t des);
extern unsigned ivl_design_consts(ivl_design_t des);
extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
/*
* These methods apply to ivl_net_const_t objects.
/* VECTOR CONSTANTS
* Vector constants are nodes with no input and a single vector
* output. The output is an array of 4-value bits, using a single char
* value for each bit.
*
* ivl_const_bits
* This returns a pointer to an array of conststant characters,
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
* terminated.
*
* ivl_const_nex
* Return the ivl_nexus_t of the output for the constant.
*
* ivl_const_signed
* Return true (!0) if the constant is a signed value, 0 otherwise.
*
* ivl_const_width
* Return the width, in logical bits, of the constant.
*
* ivl_const_pin
* ivl_const_pins
* DEPRECATED
*/
extern const char* ivl_const_bits(ivl_net_const_t net);
extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx);
extern unsigned ivl_const_pins(ivl_net_const_t net);
extern ivl_nexus_t ivl_const_nex(ivl_net_const_t net);
extern int ivl_const_signed(ivl_net_const_t net);
extern unsigned ivl_const_width(ivl_net_const_t net);
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
/* EVENTS
*
@ -545,9 +569,13 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
* the ivl_net_logic_t can represent. The various functions then
* provide access to the bits of information for a given logic device.
*
* The ivl_net_logic_t nodes are bit-slice devices. That means that
* the device may have width (and therefore processes vectors) but
* each bit slice of the width is independent.
*
* ivl_logic_type
* This method returns the type of logic gate that the cookie
* represents.
* This method returns the type of logic gate that the node
* represents. The logic type implies the meaning of the various pins.
*
* ivl_logic_name (obsolete)
* This method returns the complete name of the logic gate. Every
@ -567,6 +595,11 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
* together, then these values are the same. Use the nexus
* functions to find other pins that are connected to this nexus.
*
* ivl_logic_width
* This returns the width of the logic array. This does not affect
* the number of pins, but implies the width of the vector at each
* pin.
*
* ivl_logic_attr (obsolete)
* Return the value of a specific attribute, given the key name as
* a string. If the key is not defined, then return 0 (null).
@ -633,6 +666,10 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* These functions apply to a subset of the LPM devices, or may have
* varying meaning depending on the device:
*
* ivl_lpm_base
* The IVL_LPM_PART objects use this value as the base (first bit)
* of the part select. The ivl_lpm_width is the size of the part.
*
* ivl_lpm_data
* Return the input data nexus for device types that have a single
* input vector. This is also used to the get nexa of the first
@ -674,13 +711,16 @@ extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_sync_clr(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
/* IVL_LPM_PART */
extern unsigned ivl_lpm_base(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT IVL_LPM_RAM
IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
/* IVL_LPM_MUX IVL_LPM_UFUNC */
@ -688,8 +728,8 @@ extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
/* IVL_LPM_UFUNC */
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
IVL_LPM_UFUNC */
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
IVL_LPM_SUB IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX IVL_LPM_RAM */
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
@ -715,6 +755,11 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
* part select so that ivl_lval_pin(net, 0) is the proper bit in the
* signal.
*
* ivl_lval_width
* The width of a vector that this lval can receive. This accounts
* for the local part selecting I might to in the lval object, as
* well as the target object width.
*
* ivl_lval_mux
* If the l-value includes a bit select expression, this method
* returns an ivl_expr_t that represents that
@ -751,14 +796,17 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
* Return the number of pins for this object.
*/
extern unsigned ivl_lval_width(ivl_lval_t net);
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net);
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
extern ivl_variable_t ivl_lval_var(ivl_lval_t net);
extern unsigned ivl_lval_part_off(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
#if 0
extern unsigned ivl_lval_pins(ivl_lval_t net);
extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
#endif
/* NEXUS
* connections of signals and nodes is handled by single-bit
@ -1024,14 +1072,21 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* Signals have a name (obviously) and types. A signal may also be
* signed or unsigned.
*
* ivl_signal_pins
* ivl_signal_pins (replace these with ivl_signal_nex)
* ivl_signal_pin
* The ivl_signal_pin function returns the nexus connected to the
* signal. If the signal is a vector, the idx can be a non-zero
* value, and the result is the nexus for the specified bit.
*
* ivl_signal_nex
* This is the nexus of the signal. This is used for managing
* connections to the rest of the net. There is exactly one pin for
* a signal. If the signal represents a vector, then the entire
* vector is carried through the single output.
*
* ivl_signal_msb
* ivl_signal_lsb
* ivl_signal_width
* These functions return the left and right indices, respectively,
* of the signal. If the signal is a scalar, both return 0. However,
* it doesn't mean that the signal is a scalar if both return 0, one
@ -1077,10 +1132,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* key does not exist, the function returns 0.
*/
extern ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx);
extern unsigned ivl_signal_pins(ivl_signal_t net);
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net);
extern int ivl_signal_msb(ivl_signal_t net);
extern int ivl_signal_lsb(ivl_signal_t net);
extern unsigned ivl_signal_width(ivl_signal_t net);
extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
extern int ivl_signal_signed(ivl_signal_t net);
extern int ivl_signal_integer(ivl_signal_t net);
@ -1093,6 +1148,8 @@ extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
extern unsigned ivl_signal_attr_cnt(ivl_signal_t net);
extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
/* ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx); */
/* unsigned ivl_signal_pins(ivl_signal_t net); */
/*
* These functions get information about a process. A process is
@ -1141,10 +1198,32 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
* one type of statement, so the comment in front of them tells which
* statement types can be passed to the function.
*
* FUNCTION SUMMARY:
*
* ivl_stmt_block_scope
* If the block is named, then there is a scope associated with
* this. The code generator may need to know this in order to
* handle disable statements.
*
* ivl_stmt_rval
* Return the rval expression of the assignment. This is the value
* that is to be calculated and assigned to the l-value is
* assignment statements.
*
* SOME INTERESTING SPECIAL CASES:
*
* - IVL_ST_CASSIGN
* This reflects a procedural continuous assignment to an l-value. The
* l-value is the same as any other assignment (use ivl_stmt_lval).
*
* The value to be assigned may be an ivl_expr_t retrieved by the
* ivl_stmt_rval function. In this case, the run time is expected to
* calculate the value of the expression at the assignment, then
* continuous assign that constant value.
*
* If the ivl_stmt_rval for a CASSIGN is nil, then the ivl_stmt_nexus
* function instead contains a nexus that should be connected at run
* time to the l-value.
*/
/* IVL_ST_BLOCK, IVL_ST_FORK */
@ -1236,6 +1315,11 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.127 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.126 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*

11
main.cc
View File

@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.86 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: main.cc,v 1.87 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@ -137,7 +137,9 @@ extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*);
static struct net_func_map {
@ -149,7 +151,9 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@ -744,6 +748,11 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.87 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.86 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.18 2004/08/28 15:08:31 steve Exp $"
#ident "$Id: net_assign.cc,v 1.19 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@ -42,7 +42,7 @@ NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), var_(0), bmux_(0)
{
loff_ = 0;
lwid_ = sig_->pin_count();
lwid_ = sig_->vector_width();
sig_->incr_lref();
more = 0;
}
@ -130,7 +130,7 @@ void NetAssign_::set_part(unsigned lo, unsigned lw)
loff_ = lo;
lwid_ = lw;
if (sig_) {
assert(sig_->pin_count() >= (lo + lw));
assert(sig_->vector_width() >= (lo + lw));
} else {
assert(mem_);
assert(lwid_ == mem_->width());
@ -259,8 +259,49 @@ NetAssignNB::~NetAssignNB()
{
}
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
}
NetCAssign::~NetCAssign()
{
}
NetDeassign::NetDeassign(NetAssign_*l)
: NetAssignBase(l, 0)
{
}
NetDeassign::~NetDeassign()
{
}
NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
}
NetForce::~NetForce()
{
}
NetRelease::NetRelease(NetAssign_*l)
: NetAssignBase(l, 0)
{
}
NetRelease::~NetRelease()
{
}
/*
* $Log: net_assign.cc,v $
* Revision 1.19 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
*
@ -270,37 +311,5 @@ NetAssignNB::~NetAssignNB()
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.15 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.14 2002/08/04 18:28:15 steve
* Do not use hierarchical names of memories to
* generate vvp labels. -tdll target does not
* used hierarchical name string to look up the
* memory objects in the design.
*
* Revision 1.13 2002/07/02 03:02:57 steve
* Change the signal to a net when assignments go away.
*
* Revision 1.12 2002/06/08 23:42:46 steve
* Add NetRamDq synthsesis from memory l-values.
*
* Revision 1.11 2002/06/04 05:38:44 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.10 2002/05/26 01:39:02 steve
* Carry Verilog 2001 attributes with processes,
* all the way through to the ivl_target API.
*
* Divide signal reference counts between rval
* and lval references.
*
* Revision 1.9 2002/04/21 22:31:02 steve
* Redo handling of assignment internal delays.
* Leave it possible for them to be calculated
* at run time.
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_force.cc,v 1.12 2004/02/18 17:11:56 steve Exp $"
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@ -33,110 +33,14 @@
# include "netlist.h"
# include <assert.h>
/*
* Construct the procedural continuous assignment statement. This is a
* bit different from a normal assignment because the the lval is only
* intermittently connected. The deassign in particular disconnects
* the signals when they are not being assigned anymore. Because of
* this, there is no other reference to the lval to make it stay put
* so we increment the eref.
*
* XXXX I'm not sure this is the right way. Perhaps I should create
* output pins to connect to the netlist? But that would cause the
* link ring to grow, and that is not quite correct either. Hmm...
*/
NetCAssign::NetCAssign(NetScope*s, perm_string n, NetNet*l)
: NetNode(s, n, l->pin_count()), lval_(l)
{
lval_->incr_eref();
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx);
}
}
NetCAssign::~NetCAssign()
{
lval_->decr_eref();
}
const NetNet* NetCAssign::lval() const
{
return lval_;
}
const Link& NetCAssign::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
NetDeassign::NetDeassign(NetNet*l)
: lval_(l)
{
lval_->incr_eref();
}
NetDeassign::~NetDeassign()
{
lval_->decr_eref();
}
const NetNet*NetDeassign::lval() const
{
return lval_;
}
NetForce::NetForce(NetScope*s, perm_string n, NetNet*l)
: NetNode(s, n, l->pin_count()), lval_(l)
{
lval_->incr_eref();
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx);
}
}
NetForce::~NetForce()
{
lval_->decr_eref();
}
const Link& NetForce::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
const NetNet* NetForce::lval() const
{
return lval_;
}
NetRelease::NetRelease(NetNet*l)
: lval_(l)
{
/* Put myself into a release list that the net is
keeping. This is so that the NetNet can detach itself if
and when it is deleted by the optimizer. */
release_next_ = lval_->release_list_;
lval_->release_list_ = this;
}
NetRelease::~NetRelease()
{
assert(lval_ == 0);
}
const NetNet*NetRelease::lval() const
{
return lval_;
}
/*
* $Log: net_force.cc,v $
* Revision 1.13 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.226 2004/10/04 01:10:54 steve Exp $"
#ident "$Id: netlist.cc,v 1.227 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
@ -227,14 +227,12 @@ NetNode::~NetNode()
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, npins), sig_next_(0), sig_prev_(0),
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
release_list_ = 0;
verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE;
@ -257,25 +255,21 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
break;
}
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
pin(0).set_name(perm_string::literal("P"), 0);
pin(0).set_dir(dir);
pin(0).set_init(init_value);
scope()->add_signal(this);
s->add_signal(this);
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
: NetObj(s, n, ((ms>ls)?ms-ls:ls-ms) + 1),
: NetObj(s, n, 1),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
release_list_ = 0;
verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE;
@ -297,11 +291,9 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
break;
}
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
pin(0).set_name(perm_string::literal("P"), 0);
pin(0).set_dir(dir);
pin(0).set_init(init_value);
s->add_signal(this);
}
@ -325,14 +317,6 @@ NetNet::~NetNet()
if (scope())
scope()->rem_signal(this);
/* Detach me from all the NetRelease objects that refer to me. */
while (release_list_) {
NetRelease*tmp = release_list_;
release_list_ = tmp->release_next_;
assert(tmp->lval_ == this);
tmp->lval_ = 0;
tmp->release_next_ = 0;
}
}
NetNet::Type NetNet::type() const
@ -409,6 +393,14 @@ long NetNet::msb() const
return msb_;
}
long NetNet::vector_width() const
{
if (msb_ > lsb_)
return msb_ - lsb_ + 1;
else
return lsb_ - msb_ + 1;
}
bool NetNet::sb_is_valid(long sb) const
{
if (msb_ >= lsb_)
@ -464,7 +456,7 @@ unsigned NetNet::get_refs() const
NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid)
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid-1,0)
{
for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(sig->pin(idx+off), pin(idx));
@ -474,6 +466,33 @@ NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
set_line(*sig);
}
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid)
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
off_(off), wid_(wid)
{
connect(pin(1), sig->pin(0));
set_line(*sig);
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetPartSelect::~NetPartSelect()
{
}
unsigned NetPartSelect::width() const
{
return wid_;
}
unsigned NetPartSelect::base() const
{
return off_;
}
NetProc::NetProc()
: next_(0)
{
@ -694,33 +713,31 @@ const verinum& NetFF::sset_value() const
* 3 -- Cin
* 4 -- Cout
* 5 -- Overflow
* 6 -- DataA[0]
* 7 -- DataB[0]
* 8 -- Result[0]
* 6 -- DataA (normally a vector)
* 7 -- DataB (normally a vector)
* 8 -- Result (normally a vector)
*/
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, w*3+6)
: NetNode(s, n, 9), width_(w)
{
pin(0).set_dir(Link::INPUT); pin(0).set_name(
perm_string::literal("Add_Sub"), 0);
pin(1).set_dir(Link::INPUT); pin(1).set_name(
perm_string::literal("Aclr"), 0);
pin(2).set_dir(Link::INPUT); pin(2).set_name(
perm_string::literal("Clock"), 0);
pin(3).set_dir(Link::INPUT); pin(3).set_name(
perm_string::literal("Cin"), 0);
pin(4).set_dir(Link::OUTPUT); pin(4).set_name(
perm_string::literal("Cout"), 0);
pin(5).set_dir(Link::OUTPUT); pin(5).set_name(
perm_string::literal("Overflow"), 0);
for (unsigned idx = 0 ; idx < w ; idx += 1) {
pin_DataA(idx).set_dir(Link::INPUT);
pin_DataB(idx).set_dir(Link::INPUT);
pin_Result(idx).set_dir(Link::OUTPUT);
pin_DataA(idx).set_name(perm_string::literal("DataA"), idx);
pin_DataB(idx).set_name(perm_string::literal("DataB"), idx);
pin_Result(idx).set_name(perm_string::literal("Result"), idx);
}
pin(0).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("Add_Sub"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Aclr"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("Clock"), 0);
pin(3).set_dir(Link::INPUT);
pin(3).set_name(perm_string::literal("Cin"), 0);
pin(4).set_dir(Link::OUTPUT);
pin(4).set_name(perm_string::literal("Cout"), 0);
pin(5).set_dir(Link::OUTPUT);
pin(5).set_name(perm_string::literal("Overflow"), 0);
pin(6).set_dir(Link::INPUT);
pin(6).set_name(perm_string::literal("DataA"), 0);
pin(7).set_dir(Link::INPUT);
pin(7).set_name(perm_string::literal("DataB"), 0);
pin(8).set_dir(Link::OUTPUT);
pin(8).set_name(perm_string::literal("Result"), 0);
}
NetAddSub::~NetAddSub()
@ -729,7 +746,7 @@ NetAddSub::~NetAddSub()
unsigned NetAddSub::width()const
{
return (pin_count() - 6) / 3;
return width_;
}
Link& NetAddSub::pin_Cout()
@ -742,46 +759,34 @@ const Link& NetAddSub::pin_Cout() const
return pin(4);
}
Link& NetAddSub::pin_DataA(unsigned idx)
Link& NetAddSub::pin_DataA()
{
idx = 6 + idx*3;
assert(idx < pin_count());
return pin(idx);
return pin(6);
}
const Link& NetAddSub::pin_DataA(unsigned idx) const
const Link& NetAddSub::pin_DataA() const
{
idx = 6 + idx*3;
assert(idx < pin_count());
return pin(idx);
return pin(6);
}
Link& NetAddSub::pin_DataB(unsigned idx)
Link& NetAddSub::pin_DataB()
{
idx = 7 + idx*3;
assert(idx < pin_count());
return pin(idx);
return pin(7);
}
const Link& NetAddSub::pin_DataB(unsigned idx) const
const Link& NetAddSub::pin_DataB() const
{
idx = 7 + idx*3;
assert(idx < pin_count());
return pin(idx);
return pin(7);
}
Link& NetAddSub::pin_Result(unsigned idx)
Link& NetAddSub::pin_Result()
{
idx = 8 + idx*3;
assert(idx < pin_count());
return pin(idx);
return pin(8);
}
const Link& NetAddSub::pin_Result(unsigned idx) const
const Link& NetAddSub::pin_Result() const
{
idx = 8 + idx*3;
assert(idx < pin_count());
return pin(idx);
return pin(8);
}
/*
@ -1591,8 +1596,8 @@ const Link& NetRamDq::pin_Q(unsigned idx) const
return pin(3+awidth_+width()+idx);
}
NetBUFZ::NetBUFZ(NetScope*s, perm_string n)
: NetNode(s, n, 2)
NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
@ -1604,6 +1609,10 @@ NetBUFZ::~NetBUFZ()
{
}
unsigned NetBUFZ::width() const
{
return width_;
}
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n)
: NetNode(s, n, 3)
@ -1656,7 +1665,7 @@ NetProc* NetCondit::else_clause()
}
NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
: NetNode(s, n, 1)
: NetNode(s, n, 1), width_(1)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
@ -1665,12 +1674,12 @@ NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
}
NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
: NetNode(s, n, val.len())
: NetNode(s, n, 1), width_(val.len())
{
value_ = new verinum::V[pin_count()];
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::OUTPUT);
pin(idx).set_name(perm_string::literal("O"), idx);
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
value_ = new verinum::V[width_];
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
value_[idx] = val.get(idx);
}
}
@ -1682,10 +1691,15 @@ NetConst::~NetConst()
verinum::V NetConst::value(unsigned idx) const
{
assert(idx < pin_count());
assert(idx < width_);
return value_[idx];
}
unsigned NetConst::width() const
{
return width_;
}
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
: scope_(s), statement_(0), result_sig_(result), result_var_(0), ports_(po)
{
@ -2071,15 +2085,14 @@ const NetScope* NetEScope::scope() const
}
NetESignal::NetESignal(NetNet*n)
: NetExpr(n->pin_count()), net_(n)
: NetExpr(n->vector_width()), net_(n)
{
msi_ = n->pin_count() - 1;
lsi_ = 0;
net_->incr_eref();
set_line(*n);
cast_signed(net_->get_signed());
}
#if 0
NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
: NetExpr(m - l + 1), net_(n)
{
@ -2090,6 +2103,7 @@ NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
set_line(*n);
cast_signed(net_->get_signed());
}
#endif
NetESignal::~NetESignal()
{
@ -2103,13 +2117,13 @@ perm_string NetESignal::name() const
unsigned NetESignal::bit_count() const
{
return msi_ - lsi_ + 1;
return net_->vector_width();
}
Link& NetESignal::bit(unsigned idx)
{
assert(idx <= (msi_ - lsi_));
return net_->pin(idx + lsi_);
assert(idx <= 0);
return net_->pin(idx);
}
const NetNet* NetESignal::sig() const
@ -2119,12 +2133,12 @@ const NetNet* NetESignal::sig() const
unsigned NetESignal::lsi() const
{
return lsi_;
return net_->lsb();
}
unsigned NetESignal::msi() const
{
return msi_;
return net_->msb();
}
NetEBitSel::NetEBitSel(NetESignal*sig, NetExpr*ex)
@ -2231,8 +2245,9 @@ NetEUReduce::~NetEUReduce()
{
}
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t)
: NetNode(s, n, pins), type_(t)
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
TYPE t, unsigned wid)
: NetNode(s, n, pins), type_(t), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
@ -2242,6 +2257,16 @@ NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t)
}
}
NetLogic::TYPE NetLogic::type() const
{
return type_;
}
unsigned NetLogic::width() const
{
return width_;
}
NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
: name_(n), proc_(0), ports_(po)
{
@ -2281,6 +2306,11 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.227 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.226 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*

143
netlist.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.321 2004/10/04 01:10:54 steve Exp $"
#ident "$Id: netlist.h,v 1.322 2004/12/11 02:31:27 steve Exp $"
#endif
/*
@ -345,8 +345,11 @@ class NetNode : public NetObj {
/*
* NetNet is a special kind of NetObj that doesn't really do anything,
* but carries the properties of the wire/reg/trireg, including its
* name. A scalar wire is a NetNet with one pin, a vector a wider
* NetNet. NetNet objects also appear as side effects of synthesis or
* name. Scalers and vectors are all the same thing here, a NetNet
* with a single pin. The difference between a scaler and vector is
* the video of the atomic vector datum it carries.
*
* NetNet objects can also appear as side effects of synthesis or
* other abstractions.
*
* Note that INTEGER types are an alias for a ``reg signed [31:0]''.
@ -357,7 +360,7 @@ class NetNode : public NetObj {
*
* NetNet objects are located by searching NetScope objects.
*
* All the pins of a NetNet object are PASSIVE: they do not drive
* The pin of a NetNet object are PASSIVE: they do not drive
* anything and they are not a data sink, per se. The pins follow the
* values on the nexus.
*/
@ -397,6 +400,7 @@ class NetNet : public NetObj {
reg [1:8] has 8 bits, msb==1 and lsb==8. */
long msb() const;
long lsb() const;
long vector_width() const;
/* This method converts a signed index (the type that might be
found in the verilog source) to a pin number. It accounts
@ -431,12 +435,6 @@ class NetNet : public NetObj {
friend class NetScope;
NetNet*sig_next_, *sig_prev_;
// Keep a list of release statements that reference me. I may
// need to know this in order to fix them up when I am
// deleted.
friend class NetRelease;
NetRelease*release_list_;
private:
Type type_;
PortType port_type_;
@ -472,18 +470,21 @@ class NetAddSub : public NetNode {
Link& pin_Cout();
Link& pin_Overflow();
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
const Link& pin_Cout() const;
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
const Link& pin_DataA() const;
const Link& pin_DataB() const;
const Link& pin_Result() 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:
unsigned width_;
};
/*
@ -1122,7 +1123,7 @@ class NetECRealParam : public NetECReal {
perm_string name_;
};
/*
/* DEPRECATED -- REMOVE ME! Use NetPartSelect instead.
* This is a special, magical NetNet object. It represents a constant
* bit or part select of another NetNet, so is used to return that
* selection from elaborate function. None of these should remain once
@ -1135,6 +1136,29 @@ class NetSubnet : public NetNet {
virtual void dump_net(ostream&, unsigned) const;
};
/*
* The NetPartSelect device represents an r-value part select of a
* signal. The output (pin 0) is a vector that is a part select of the
* input (pin 1). The part to be selected is the canonical (0-based)
* offset and the specified number of bits (wid).
*/
class NetPartSelect : public NetNode {
public:
explicit NetPartSelect(NetNet*sig, unsigned off, unsigned wid);
~NetPartSelect();
unsigned width() const;
unsigned base() const;
virtual void dump_node(ostream&, unsigned ind) const;
bool emit_node(struct target_t*tgt) const;
private:
unsigned off_;
unsigned wid_;
};
/*
* The NetBUFZ is a magic device that represents the continuous
* assign, with the output being the target register and the input
@ -1145,11 +1169,16 @@ class NetSubnet : public NetNet {
class NetBUFZ : public NetNode {
public:
explicit NetBUFZ(NetScope*s, perm_string n);
explicit NetBUFZ(NetScope*s, perm_string n, unsigned wid);
~NetBUFZ();
unsigned width() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
};
/*
@ -1189,12 +1218,14 @@ class NetConst : public NetNode {
~NetConst();
verinum::V value(unsigned idx) const;
unsigned width() const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*, functor_t*);
virtual void dump_node(ostream&, unsigned ind) const;
private:
unsigned width_;
verinum::V*value_;
};
@ -1219,16 +1250,19 @@ class NetLogic : public NetNode {
NOTIF0, NOTIF1, OR, PULLDOWN, PULLUP, RNMOS, RPMOS,
PMOS, XNOR, XOR };
explicit NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t);
explicit NetLogic(NetScope*s, perm_string n, unsigned pins,
TYPE t, unsigned wid);
TYPE type() const { return type_; }
TYPE type() const;
unsigned width() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*, functor_t*);
private:
const TYPE type_;
TYPE type_;
unsigned width_;
};
/*
@ -1627,31 +1661,17 @@ class NetCase : public NetProc {
/*
* The cassign statement causes the r-val net to be forced onto the
* l-val reg when it is executed. The code generator is expected to
* know what that means. All the expressions are structural and behave
* like nets.
*
* This class is a NetProc because it it turned on by procedural
* behavior. However, it is also a NetNode because it connects to
* nets, and when activated follows the net values.
* know what that means.
*/
class NetCAssign : public NetProc, public NetNode {
class NetCAssign : public NetAssignBase {
public:
explicit NetCAssign(NetScope*s, perm_string n, NetNet*l);
explicit NetCAssign(NetAssign_*lv, NetExpr*rv);
~NetCAssign();
const Link& lval_pin(unsigned) const;
virtual NexusSet* nex_input();
virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
const NetNet*lval() const;
private:
NetNet*lval_;
private: // not implemented
NetCAssign(const NetCAssign&);
@ -1709,20 +1729,15 @@ class NetCondit : public NetProc {
* lval is the expression of the "deassign <expr>;" statement with the
* expr elaborated to a net.
*/
class NetDeassign : public NetProc {
class NetDeassign : public NetAssignBase {
public:
explicit NetDeassign(NetNet*l);
explicit NetDeassign(NetAssign_*l);
~NetDeassign();
const NetNet*lval() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetNet*lval_;
private: // not implemented
NetDeassign(const NetDeassign&);
NetDeassign& operator= (const NetDeassign&);
@ -1957,32 +1972,18 @@ class NetEvProbe : public NetNode {
/*
* The force statement causes the r-val net to be forced onto the
* l-val net when it is executed. The code generator is expected to
* know what that means. All the expressions are structural and behave
* like nets.
*
* This class is a NetProc because it it turned on by procedural
* behavior. However, it is also a NetNode because it connects to
* nets, and when activated follows the net values.
* know what that means.
*/
class NetForce : public NetProc, public NetNode {
class NetForce : public NetAssignBase {
public:
explicit NetForce(NetScope*s, perm_string n, NetNet*l);
explicit NetForce(NetAssign_*l, NetExpr*r);
~NetForce();
const Link& lval_pin(unsigned) const;
const NetNet*lval() const;
virtual NexusSet* nex_input();
virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
NetNet*lval_;
};
/*
@ -2110,22 +2111,16 @@ class NetRepeat : public NetProc {
* lval is the expression of the "release <expr>;" statement with the
* expr elaborated to a net.
*/
class NetRelease : public NetProc {
class NetRelease : public NetAssignBase {
public:
explicit NetRelease(NetNet*l);
explicit NetRelease(NetAssign_*l);
~NetRelease();
const NetNet*lval() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetNet*lval_;
// Used to manage list within NetNet objects.
friend class NetNet;
NetRelease*release_next_;
};
@ -2954,7 +2949,6 @@ class NetESignal : public NetExpr {
public:
NetESignal(NetNet*n);
NetESignal(NetNet*n, unsigned msi, unsigned lsi);
~NetESignal();
perm_string name() const;
@ -2978,8 +2972,6 @@ class NetESignal : public NetExpr {
private:
NetNet*net_;
unsigned msi_;
unsigned lsi_;
};
/*
@ -3357,6 +3349,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.322 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.321 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $"
#ident "$Id: netmisc.cc,v 1.9 2004/12/11 02:31:27 steve Exp $"
#endif
# include "config.h"
@ -30,7 +30,7 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
{
if (val == 0)
return sig;
#if 0
NetScope*scope = sig->scope();
unsigned long abs_val = (val >= 0)? val : (-val);
unsigned width = sig->pin_count();
@ -70,6 +70,10 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
des->add_node(val_c);
return res;
#else
cerr << sig->get_line() << ": XXXX: Forgot how to implement add_to_net" << endl;
return 0;
#endif
}
@ -90,6 +94,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/*
* $Log: netmisc.cc,v $
* Revision 1.9 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.8 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.129 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: pform.cc,v 1.130 2004/12/11 02:31:27 steve Exp $"
#endif
# include "config.h"
@ -952,7 +952,7 @@ void pform_make_modgates(perm_string type,
delete gates;
}
PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
svector<PExpr*>*del,
struct str_pair_t str)
{
@ -1597,6 +1597,11 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* Revision 1.130 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.129 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*

10
pform.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $"
#ident "$Id: pform.h,v 1.82 2004/12/11 02:31:27 steve Exp $"
#endif
# include "netlist.h"
@ -270,9 +270,6 @@ extern void pform_make_modgates(perm_string type,
svector<lgate>*gates);
/* Make a continuous assignment node, with optional bit- or part- select. */
extern PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
svector<PExpr*>*delays,
struct str_pair_t str);
extern void pform_make_pgassign_list(svector<PExpr*>*alist,
svector<PExpr*>*del,
struct str_pair_t str,
@ -298,6 +295,11 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.82 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.81 2004/08/26 04:02:04 steve
* Add support for localparam ranges.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.39 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: synth2.cc,v 1.40 2004/12/11 02:31:27 steve Exp $"
#endif
# include "config.h"
@ -768,7 +768,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
if (ff->pin_Enable().is_linked()) {
NetLogic*ce_and = new NetLogic(scope,
scope->local_symbol(), 3,
NetLogic::AND);
NetLogic::AND, 1);
des->add_node(ce_and);
connect(ff->pin_Enable(), ce_and->pin(1));
connect(ce->pin(0), ce_and->pin(2));
@ -985,6 +985,11 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.40 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.39 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.108 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.109 2004/12/11 02:31:27 steve Exp $"
#endif
# include "config.h"
@ -129,20 +129,10 @@ extern "C" const char*ivl_const_bits(ivl_net_const_t net)
return net->b.bits_;
}
extern "C" ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_const_nex(ivl_net_const_t net)
{
assert(net);
assert(idx < net->width_);
if (net->width_ == 1)
return net->n.pin_;
else
return net->n.pins_[idx];
}
extern "C" unsigned ivl_const_pins(ivl_net_const_t net)
{
assert(net);
return net->width_;
return net->pin_;
}
extern "C" int ivl_const_signed(ivl_net_const_t net)
@ -151,6 +141,12 @@ extern "C" int ivl_const_signed(ivl_net_const_t net)
return net->signed_;
}
extern "C" unsigned ivl_const_width(ivl_net_const_t net)
{
assert(net);
return net->width_;
}
extern "C" const char* ivl_event_name(ivl_event_t net)
{
static char*name_buffer = 0;
@ -585,6 +581,11 @@ extern "C" unsigned ivl_logic_delay(ivl_net_logic_t net, unsigned transition)
return net->delay[transition];
}
extern "C" unsigned ivl_logic_width(ivl_net_logic_t net)
{
assert(net);
return net->width_;
}
extern "C" unsigned ivl_udp_sequ(ivl_udp_t net)
{
@ -673,6 +674,18 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
}
}
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_PART:
return net->u_.part.base;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
{
assert(net);
@ -749,8 +762,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
assert(idx < net->u_.arith.width);
return net->u_.arith.a[idx];
assert(idx == 0);
return net->u_.arith.a;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
@ -765,6 +778,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
else
return net->u_.ff.d.pins[idx];
case IVL_LPM_PART:
assert(idx == 0);
return net->u_.part.a;
default:
assert(0);
return 0;
@ -785,8 +802,8 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
assert(idx < net->u_.arith.width);
return net->u_.arith.b[idx];
assert(idx == 0);
return net->u_.arith.b;
default:
assert(0);
@ -873,15 +890,15 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
assert(idx < net->u_.arith.width);
return net->u_.arith.q[idx];
assert(idx == 0);
return net->u_.arith.q;
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE:
assert(idx == 0);
return net->u_.arith.q[0];
return net->u_.arith.q;
case IVL_LPM_FF:
case IVL_LPM_RAM:
@ -907,6 +924,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
assert(idx < net->u_.ufunc.port_wid[0]);
return net->u_.ufunc.pins[idx];
case IVL_LPM_PART:
assert(idx == 0);
return net->u_.part.q;
default:
assert(0);
return 0;
@ -987,6 +1008,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return 0;
case IVL_LPM_UFUNC:
return 0;
case IVL_LPM_PART:
return net->u_.part.signed_flag;
default:
assert(0);
return 0;
@ -1035,6 +1058,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
return net->u_.shift.width;
case IVL_LPM_UFUNC:
return net->u_.ufunc.port_wid[0];
case IVL_LPM_PART:
return net->u_.part.width;
default:
assert(0);
return 0;
@ -1091,12 +1116,20 @@ extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
return net->loff_;
}
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
extern "C" unsigned ivl_lval_width(ivl_lval_t net)
{
assert(net);
return net->width_;
}
#if 0
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
{
assert(net);
return net->width_;
}
#endif
#if 0
extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
{
assert(net);
@ -1104,6 +1137,7 @@ extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
assert(net->type_ != IVL_LVAL_MEM);
return ivl_signal_pin(net->n.sig, idx+net->loff_);
}
#endif
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
{
@ -1504,21 +1538,9 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
return name_buffer;
}
extern "C" ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
{
assert(net);
assert(idx < net->width_);
if (net->width_ == 1) {
return net->n.pin_;
} else {
return net->n.pins_[idx];
}
}
extern "C" unsigned ivl_signal_pins(ivl_signal_t net)
{
return net->width_;
return net->pin_;
}
extern "C" int ivl_signal_msb(ivl_signal_t net)
@ -1532,6 +1554,11 @@ extern "C" int ivl_signal_lsb(ivl_signal_t net)
return net->lsb_index;
}
extern "C" unsigned ivl_signal_width(ivl_signal_t net)
{
return net->width_;
}
extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
{
return net->port_;
@ -1760,15 +1787,12 @@ extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx)
switch (net->type_) {
case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB:
assert(idx < net->u_.assign_.lvals_);
return net->u_.assign_.lval_ + idx;
case IVL_ST_CASSIGN:
case IVL_ST_DEASSIGN:
case IVL_ST_FORCE:
case IVL_ST_RELEASE:
assert(idx < net->u_.cassign_.lvals);
return net->u_.cassign_.lval + idx;
assert(idx < net->u_.assign_.lvals_);
return net->u_.assign_.lval_ + idx;
default:
assert(0);
@ -1781,13 +1805,11 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
switch (net->type_) {
case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB:
return net->u_.assign_.lvals_;
case IVL_ST_CASSIGN:
case IVL_ST_DEASSIGN:
case IVL_ST_FORCE:
case IVL_ST_RELEASE:
return net->u_.cassign_.lvals;
return net->u_.assign_.lvals_;
default:
assert(0);
@ -1798,17 +1820,25 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
{
assert((net->type_ == IVL_ST_ASSIGN)
|| (net->type_ == IVL_ST_ASSIGN_NB));
|| (net->type_ == IVL_ST_ASSIGN_NB)
|| (net->type_ == IVL_ST_CASSIGN)
|| (net->type_ == IVL_ST_DEASSIGN));
unsigned sum = 0;
for (unsigned idx = 0 ; idx < net->u_.assign_.lvals_ ; idx += 1) {
ivl_lval_t cur = net->u_.assign_.lval_ + idx;
unsigned nlvals;
struct ivl_lval_s*lvals;
nlvals = net->u_.assign_.lvals_;
lvals = net->u_.assign_.lval_;
for (unsigned idx = 0 ; idx < nlvals ; idx += 1) {
ivl_lval_t cur = lvals + idx;
switch(cur->type_) {
case IVL_LVAL_MUX:
sum += 1;
break;
case IVL_LVAL_REG:
sum += ivl_lval_pins(cur);
sum += ivl_lval_width(cur);
break;
case IVL_LVAL_MEM:
sum += ivl_memory_width(ivl_lval_mem(cur));
@ -1836,33 +1866,6 @@ extern "C" const char* ivl_stmt_name(ivl_statement_t net)
return 0;
}
extern "C" ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx)
{
switch (net->type_) {
case IVL_ST_CASSIGN:
case IVL_ST_FORCE:
assert(idx < net->u_.cassign_.npins);
return net->u_.cassign_.pins[idx];
default:
assert(0);
}
return 0;
}
extern "C" unsigned ivl_stmt_nexus_count(ivl_statement_t net)
{
switch (net->type_) {
case IVL_ST_CASSIGN:
case IVL_ST_FORCE:
return net->u_.cassign_.npins;
default:
assert(0);
}
return 0;
}
extern "C" ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx)
{
switch (net->type_) {
@ -1892,6 +1895,7 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net)
switch (net->type_) {
case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB:
case IVL_ST_CASSIGN:
return net->u_.assign_.rval_;
default:
assert(0);
@ -1935,6 +1939,11 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.109 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.108 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-proc.cc,v 1.65 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: t-dll-proc.cc,v 1.66 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
@ -145,90 +145,15 @@ bool dll_target::func_def(const NetScope*net)
}
/*
* This private function makes the assignment lvals for the various
* kinds of assignment statements.
*/
void dll_target::proc_assign(const NetAssign*net)
void dll_target::make_assign_lvals_(const NetAssignBase*net)
{
unsigned cnt;
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN;
stmt_cur_->u_.assign_.lvals_ = cnt = net->l_val_count();
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
stmt_cur_->u_.assign_.delay = 0;
/* The assignment may have multiple concatenated
l-values. Scan them and accumulate an ivl_lval_t list. */
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
const NetAssign_*asn = net->l_val(idx);
cur->width_ = asn->lwidth();
cur->loff_ = asn->get_loff();
if (asn->sig()) {
cur->type_ = IVL_LVAL_REG;
cur->n.sig = find_signal(des_, asn->sig());
cur->idx = 0;
if (asn->bmux()) {
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
if (cur->n.sig->lsb_index != 0)
sub_off_from_expr_(asn->sig()->lsb());
if (cur->n.sig->lsb_dist != 1)
mul_expr_by_const_(cur->n.sig->lsb_dist);
cur->type_ = IVL_LVAL_MUX;
cur->idx = expr_;
expr_ = 0;
}
} else if (asn->var()) {
cur->type_ = IVL_LVAL_VAR;
cur->idx = 0;
cur->n.var = find_variable(des_, asn->var());
} else {
assert(asn->mem());
cur->type_ = IVL_LVAL_MEM;
cur->n.mem = find_memory(des_, asn->mem());
assert(cur->n.mem);
cur->width_ = ivl_memory_width(cur->n.mem);
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
cur->idx = expr_;
expr_ = 0;
}
}
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
const NetExpr*del = net->get_delay();
if (del) {
del->expr_scan(this);
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
}
void dll_target::proc_assign_nb(const NetAssignNB*net)
{
unsigned cnt = net->l_val_count();
const NetExpr* delay_exp = net->get_delay();
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
stmt_cur_->u_.assign_.lvals_ = cnt;
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
stmt_cur_->u_.assign_.delay = 0;
@ -276,7 +201,49 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
}
}
}
/*
*/
void dll_target::proc_assign(const NetAssign*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN;
stmt_cur_->u_.assign_.delay = 0;
/* Make the lval fields. */
make_assign_lvals_(net);
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
const NetExpr*del = net->get_delay();
if (del) {
del->expr_scan(this);
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
}
void dll_target::proc_assign_nb(const NetAssignNB*net)
{
const NetExpr* delay_exp = net->get_delay();
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
stmt_cur_->u_.assign_.delay = 0;
/* Make the lval fields. */
make_assign_lvals_(net);
/* Make the rval field. */
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
@ -428,27 +395,13 @@ bool dll_target::proc_cassign(const NetCAssign*net)
stmt_cur_->type_ = IVL_ST_CASSIGN;
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
/* Make the l-value fields. */
make_assign_lvals_(net);
const NetNet*lsig = net->lval();
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
stmt_cur_->u_.cassign_.npins = net->pin_count();
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
assert(ntmp[idx]);
}
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
return true;
}
@ -485,19 +438,9 @@ bool dll_target::proc_deassign(const NetDeassign*net)
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_DEASSIGN;
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
const NetNet*lsig = net->lval();
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
stmt_cur_->u_.cassign_.npins = 0;
stmt_cur_->u_.cassign_.pins = 0;
/* Make the l-value fields. */
make_assign_lvals_(net);
return true;
}
@ -554,52 +497,19 @@ bool dll_target::proc_disable(const NetDisable*net)
bool dll_target::proc_force(const NetForce*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_FORCE;
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
/* Make the l-value fields. */
make_assign_lvals_(net);
const NetNet*lsig = net->lval();
assert(lsig);
ivl_signal_t sig = find_signal(des_, lsig);
assert(sig);
ivl_lval_type_t ltype;
switch (sig->type_) {
case IVL_SIT_REG:
ltype = IVL_LVAL_REG;
break;
case IVL_SIT_TRI:
case IVL_SIT_TRI0:
case IVL_SIT_TRI1:
ltype = IVL_LVAL_NET;
break;
default:
cerr << net->get_line() << ": internal error: Sorry, "
<< "force to nets not supported by this target."
<< endl;
return false;
}
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
stmt_cur_->u_.cassign_.npins = net->pin_count();
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
assert(ntmp[idx]);
}
assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
return true;
}
@ -630,47 +540,8 @@ bool dll_target::proc_release(const NetRelease*net)
stmt_cur_->type_ = IVL_ST_RELEASE;
/* If there is no signal attached to the release, then it is
the victim of an elided net. In that case, simply state
that there are no lvals, and that's all. */
const NetNet*lsig = net->lval();
if (lsig == 0) {
stmt_cur_->u_.cassign_.lvals = 0;
return true;
}
assert(lsig);
stmt_cur_->u_.cassign_.lvals = 1;
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
calloc(1, sizeof(struct ivl_lval_s));
ivl_signal_t sig = find_signal(des_, lsig);
assert(sig);
ivl_lval_type_t ltype;
switch (sig->type_) {
case IVL_SIT_REG:
ltype = IVL_LVAL_REG;
break;
case IVL_SIT_TRI:
case IVL_SIT_TRI0:
case IVL_SIT_TRI1:
ltype = IVL_LVAL_NET;
break;
default:
cerr << net->get_line() << ": internal error: Sorry, "
<< "force/release to nets not supported by this target."
<< endl;
return false;
}
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
stmt_cur_->u_.cassign_.lval[0].idx = 0;
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
/* Make the l-value fields. */
make_assign_lvals_(net);
return true;
}
@ -872,6 +743,11 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* Revision 1.66 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.65 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*

194
t-dll.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.131 2004/10/04 01:10:55 steve Exp $"
#ident "$Id: t-dll.cc,v 1.132 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
@ -650,8 +650,8 @@ bool dll_target::bufz(const NetBUFZ*net)
assert(net->pin_count() == 2);
obj->type_ = IVL_LO_BUFZ;
obj->npins_ = 2;
obj->width_= net->width();
obj->npins_= 2;
obj->pins_ = new ivl_nexus_t[2];
/* Get the ivl_nexus_t objects connected to the two pins.
@ -780,6 +780,8 @@ void dll_target::logic(const NetLogic*net)
{
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
obj->width_ = net->width();
switch (net->type()) {
case NetLogic::AND:
obj->type_ = IVL_LO_AND;
@ -943,16 +945,6 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
scope_add_logic(scope, obj);
}
bool dll_target::net_cassign(const NetCAssign*)
{
return false;
}
bool dll_target::net_force(const NetForce*net)
{
return true;
}
/*
* An IVL_LPM_UFUNC represents a node in a combinational expression
* that calls a user defined function. I create an LPM object that has
@ -1119,38 +1111,31 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
obj->u_.arith.width += 1;
}
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
const Nexus*nex;
const Nexus*nex;
nex = net->pin_Result(idx).nexus();
assert(nex->t_cookie());
nex = net->pin_Result().nexus();
assert(nex->t_cookie());
obj->u_.arith.q[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
nex = net->pin_DataA(idx).nexus();
assert(nex->t_cookie());
nex = net->pin_DataA().nexus();
assert(nex->t_cookie());
obj->u_.arith.a[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
nex = net->pin_DataB(idx).nexus();
assert(nex->t_cookie());
nex = net->pin_DataB().nexus();
assert(nex->t_cookie());
obj->u_.arith.b[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.b[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
/* If the carry output is connected, then connect the extra Q
pin to the carry nexus and zero the a and b inputs. */
if (net->pin_Cout().is_linked()) {
#if 0
unsigned carry = obj->u_.arith.width - 1;
const Nexus*nex = net->pin_Cout().nexus();
assert(nex->t_cookie());
@ -1161,6 +1146,9 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
obj->u_.arith.a[carry] = 0;
obj->u_.arith.b[carry] = 0;
#else
cerr << "XXXX: t-dll.cc: Forgot how to connect cout." << endl;
#endif
}
scope_add_lpm(obj->scope, obj);
@ -1252,7 +1240,7 @@ void dll_target::lpm_compare(const NetCompare*net)
obj->u_.arith.width = net->width();
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
#if 0
obj->u_.arith.q = new ivl_nexus_t[1 + 2 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + 1;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
@ -1347,7 +1335,9 @@ void dll_target::lpm_compare(const NetCompare*net)
nexus_lpm_add(obj->u_.arith.b[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
#else
cerr << "XXXX: t-dll.cc: Forgot how to handle lpm_compare." << endl;
#endif
scope_add_lpm(obj->scope, obj);
}
@ -1365,7 +1355,7 @@ void dll_target::lpm_divide(const NetDivide*net)
obj->u_.arith.width = wid;
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
#if 0
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
@ -1418,7 +1408,9 @@ void dll_target::lpm_divide(const NetDivide*net)
obj->u_.arith.b[idx] = 0;
}
}
#else
cerr << "XXXX t-dll.cc: Forgot how to handle lpm_divide." << endl;
#endif
scope_add_lpm(obj->scope, obj);
}
@ -1438,7 +1430,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
wid = net->width_b();
obj->u_.arith.width = wid;
#if 0
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
@ -1485,7 +1477,9 @@ void dll_target::lpm_modulo(const NetModulo*net)
obj->u_.arith.b[idx] = 0;
}
}
#else
cerr << "XXXX: t-dll.cc: Forgot how to handle lpm_modulo." << endl;
#endif
scope_add_lpm(obj->scope, obj);
}
@ -1732,6 +1726,7 @@ void dll_target::lpm_mult(const NetMult*net)
obj->u_.arith.width = wid;
#if 0
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
@ -1791,7 +1786,9 @@ void dll_target::lpm_mult(const NetMult*net)
obj->u_.arith.b[idx] = 0;
}
}
#else
cerr << "XXXX: t-dll.cc: Forgot how to handle lpm_mult." << endl;
#endif
scope_add_lpm(obj->scope, obj);
}
@ -1870,6 +1867,42 @@ void dll_target::lpm_mux(const NetMux*net)
}
bool dll_target::part_select(const NetPartSelect*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_PART;
obj->name = net->name(); // NetPartSelect names are permallocated.
assert(net->scope());
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.part.signed_flag = 0;
/* Choose the width of the part select. */
obj->u_.part.width = net->width();
obj->u_.part.base = net->base();
obj->u_.part.signed_flag = 0;
const Nexus*nex;
/* NetPartSelect:pin(0) is the output pin. */
nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.part.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.part.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
/* NetPartSelect:pin(1) is the input pin. */
nex = net->pin(1).nexus();
assert(nex->t_cookie());
obj->u_.part.a = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.part.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
scope_add_lpm(obj->scope, obj);
return true;
}
/*
* The assignment l-values are captured by the assignment statements
* themselves in the process handling.
@ -1885,7 +1918,10 @@ bool dll_target::net_const(const NetConst*net)
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
obj->width_ = net->pin_count();
/* constants have a single vector output. */
assert(net->pin_count() == 1);
obj->width_ = net->width();
if (obj->width_ <= sizeof(char*)) {
bits = obj->b.bit_;
@ -1913,30 +1949,14 @@ bool dll_target::net_const(const NetConst*net)
/* Connect to all the nexus objects. Note that the one-bit
case can be handled more efficiently without allocating
array space. */
if (obj->width_ == 1) {
ivl_drive_t drv0, drv1;
drive_from_link(net->pin(0), drv0, drv1);
const Nexus*nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->n.pin_ = (ivl_nexus_t) nex->t_cookie();
nexus_con_add(obj->n.pin_, obj, 0, drv0, drv1);
} else {
obj->n.pins_ = new ivl_nexus_t[obj->width_];
for (unsigned idx = 0 ; idx < obj->width_ ; idx += 1) {
if (! net->pin(idx).is_linked())
continue;
ivl_drive_t drv0, drv1;
drive_from_link(net->pin(0), drv0, drv1);
const Nexus*nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->pin_ = (ivl_nexus_t) nex->t_cookie();
nexus_con_add(obj->pin_, obj, 0, drv0, drv1);
ivl_drive_t drv0, drv1;
drive_from_link(net->pin(idx), drv0, drv1);
const Nexus*nex = net->pin(idx).nexus();
assert(nex->t_cookie());
obj->n.pins_[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_con_add(obj->n.pins_[idx], obj, idx, drv0, drv1);
}
}
des_.nconsts += 1;
des_.consts = (ivl_net_const_t*)
@ -2057,7 +2077,7 @@ void dll_target::signal(const NetNet*net)
/* Save the primitive properties of the signal in the
ivl_signal_t object. */
obj->width_ = net->pin_count();
obj->width_ = net->vector_width();
obj->signed_= net->get_signed()? 1 : 0;
obj->lsb_index = net->lsb();
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1;
@ -2140,39 +2160,18 @@ void dll_target::signal(const NetNet*net)
t_cookie of the Nexus object so that I find it again when I
next encounter the nexus. */
if (obj->width_ == 1) {
const Nexus*nex = net->pin(0).nexus();
if (nex->t_cookie()) {
obj->n.pin_ = (ivl_nexus_t)nex->t_cookie();
nexus_sig_add(obj->n.pin_, obj, 0);
} else {
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
tmp->name_ = strings_.add(nex->name());
nex->t_cookie(tmp);
obj->n.pin_ = tmp;
}
const Nexus*nex = net->pin(0).nexus();
if (nex->t_cookie()) {
obj->pin_ = (ivl_nexus_t)nex->t_cookie();
nexus_sig_add(obj->pin_, obj, 0);
} else {
unsigned idx;
obj->n.pins_ = (ivl_nexus_t*)
calloc(obj->width_, sizeof(ivl_nexus_t));
for (idx = 0 ; idx < obj->width_ ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus();
if (nex->t_cookie()) {
obj->n.pins_[idx] = (ivl_nexus_t)nex->t_cookie();
nexus_sig_add(obj->n.pins_[idx], obj, idx);
} else {
ivl_nexus_t tmp = nexus_sig_make(obj, idx);
tmp->name_ = strings_.add(nex->name());
nex->t_cookie(tmp);
obj->n.pins_[idx] = tmp;
}
}
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
tmp->name_ = strings_.add(nex->name());
nex->t_cookie(tmp);
obj->pin_ = tmp;
}
}
extern const struct target tgt_dll = { "dll", &dll_target_obj };
@ -2180,6 +2179,11 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.132 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.131 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space.
*

41
t-dll.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.115 2004/10/04 01:10:56 steve Exp $"
#ident "$Id: t-dll.h,v 1.116 2004/12/11 02:31:28 steve Exp $"
#endif
# include "target.h"
@ -82,9 +82,8 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_mult(const NetMult*);
void lpm_mux(const NetMux*);
void lpm_ram_dq(const NetRamDq*);
bool part_select(const NetPartSelect*);
void net_assign(const NetAssign_*);
bool net_cassign(const NetCAssign*);
bool net_force(const NetForce*);
bool net_function(const NetUserFunc*);
bool net_const(const NetConst*);
void net_probe(const NetEvProbe*);
@ -162,6 +161,7 @@ struct dll_target : public target_t, public expr_scan_t {
void add_root(ivl_design_s &des_, const NetScope *s);
void make_assign_lvals_(const NetAssignBase*net);
void sub_off_from_expr_(long);
void mul_expr_by_const_(long);
@ -344,9 +344,16 @@ struct ivl_lpm_s {
struct ivl_lpm_arith_s {
unsigned width;
unsigned signed_flag :1;
ivl_nexus_t*q, *a, *b;
ivl_nexus_t q, a, b;
} arith;
struct ivl_part_s {
unsigned width;
unsigned base;
unsigned signed_flag :1;
ivl_nexus_t q, a;
} part;
struct ivl_lpm_ufunc_s {
ivl_scope_t def;
unsigned ports;
@ -395,10 +402,7 @@ struct ivl_net_const_s {
char *bits_;
} b;
union {
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
ivl_nexus_t pin_;
};
/*
@ -407,6 +411,7 @@ struct ivl_net_const_s {
*/
struct ivl_net_logic_s {
ivl_logic_t type_;
unsigned width_;
ivl_udp_t udp;
perm_string name_;
@ -578,10 +583,7 @@ struct ivl_signal_s {
perm_string name_;
ivl_scope_t scope_;
union {
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
ivl_nexus_t pin_;
struct ivl_attribute_s*attr;
unsigned nattr;
@ -595,7 +597,8 @@ struct ivl_signal_s {
struct ivl_statement_s {
enum ivl_statement_type_e type_;
union {
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB */
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB
IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
unsigned lvals_;
struct ivl_lval_s*lval_;
ivl_expr_t rval_;
@ -615,13 +618,6 @@ struct ivl_statement_s {
struct ivl_statement_s*case_st;
} case_;
struct { /* IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
unsigned lvals;
struct ivl_lval_s*lval;
unsigned npins;
ivl_nexus_t*pins;
} cassign_;
struct { /* IVL_ST_CONDIT */
/* This is the condition expression */
ivl_expr_t cond_;
@ -684,6 +680,11 @@ struct ivl_variable_s {
/*
* $Log: t-dll.h,v $
* Revision 1.116 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.115 2004/10/04 01:10:56 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $"
#ident "$Id: target.cc,v 1.70 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
@ -137,20 +137,19 @@ void target_t::lpm_ram_dq(const NetRamDq*)
"Unhandled NetRamDq." << endl;
}
bool target_t::part_select(const NetPartSelect*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetPartSelect." << endl;
return false;
}
void target_t::net_case_cmp(const NetCaseCmp*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled case compare node." << endl;
}
bool target_t::net_cassign(const NetCAssign*dev)
{
cerr << "target (" << typeid(*this).name() << "): ";
cerr << dev->get_line();
cerr << ": Target does not support procedural continuous assignment." << endl;
return false;
}
bool target_t::net_const(const NetConst*)
{
cerr << "target (" << typeid(*this).name() << "): "
@ -158,13 +157,6 @@ bool target_t::net_const(const NetConst*)
return false;
}
bool target_t::net_force(const NetForce*dev)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetForce node." << endl;
return false;
}
bool target_t::net_function(const NetUserFunc*net)
{
cerr << "target (" << typeid(*this).name() << "): "
@ -420,6 +412,11 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.70 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.69 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $"
#ident "$Id: target.h,v 1.66 2004/12/11 02:31:28 steve Exp $"
#endif
# include "netlist.h"
@ -86,14 +86,14 @@ struct target_t {
virtual void lpm_mux(const NetMux*);
virtual void lpm_ram_dq(const NetRamDq*);
virtual bool part_select(const NetPartSelect*);
/* Output a gate (called for each gate) */
virtual void logic(const NetLogic*);
virtual bool bufz(const NetBUFZ*);
virtual void udp(const NetUDP*);
virtual void net_case_cmp(const NetCaseCmp*);
virtual bool net_cassign(const NetCAssign*);
virtual bool net_const(const NetConst*);
virtual bool net_force(const NetForce*);
virtual bool net_function(const NetUserFunc*);
virtual void net_probe(const NetEvProbe*);
@ -170,6 +170,11 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.66 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.65 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: targets.cc,v 1.11 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: targets.cc,v 1.12 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
@ -25,17 +25,25 @@
# include "target.h"
extern const struct target tgt_dll;
#ifdef WITH_T_XNF
extern const struct target tgt_xnf;
#endif
const struct target *target_table[] = {
&tgt_dll,
#ifdef WITH_T_XNF
&tgt_xnf,
#endif
0
};
/*
* $Log: targets.cc,v $
* Revision 1.12 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.11 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.90 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: stub.c,v 1.91 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
@ -184,6 +184,7 @@ static void show_expression(ivl_expr_t net, unsigned ind)
static void show_lpm(ivl_lpm_t net)
{
unsigned idx;
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net);
switch (ivl_lpm_type(net)) {
@ -191,19 +192,11 @@ static void show_lpm(ivl_lpm_t net)
case IVL_LPM_ADD: {
fprintf(out, " LPM_ADD %s: <width=%u>\n",
ivl_lpm_basename(net), width);
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx);
fprintf(out, " Data A %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_datab(net, idx);
fprintf(out, " Data B %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
fprintf(out, " Q: %s\n", ivl_nexus_name(ivl_lpm_q(net, 0)));
nex = ivl_lpm_data(net, 0);
fprintf(out, " DataA: %s\n", nex? ivl_nexus_name(nex) : "");
ivl_nexus_t nex = ivl_lpm_datab(net, 0);
fprintf(out, " DataB: %s\n", nex? ivl_nexus_name(nex) : "");
break;
}
@ -367,6 +360,15 @@ static void show_lpm(ivl_lpm_t net)
break;
}
case IVL_LPM_PART: {
fprintf(out, " LPM_PART %s: <width=%u, base=%u, signed=%d>\n",
ivl_lpm_basename(net),
width, ivl_lpm_base(net), ivl_lpm_signed(net));
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
break;
}
default:
fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n",
ivl_lpm_type(net),
@ -396,17 +398,13 @@ static void show_assign_lval(ivl_lval_t lval, unsigned ind)
} else {
unsigned pp;
ivl_nexus_t nex = ivl_lval_pin(lval, 0);
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_nexus_t nex = ivl_signal_nex(sig);
fprintf(out, "%*spart_off=%u {%s", ind, "",
ivl_lval_part_off(lval),
ivl_nexus_name(nex));
fprintf(out, "<nptrs=%u>", ivl_nexus_ptrs(nex));
for (pp = 1 ; pp < ivl_lval_pins(lval) ; pp += 1) {
nex = ivl_lval_pin(lval, pp);
fprintf(out, ", %s", ivl_nexus_name(nex));
fprintf(out, "<nptrs=%u>", ivl_nexus_ptrs(nex));
}
fprintf(out, "}\n");
}
}
@ -481,6 +479,17 @@ static void show_statement(ivl_statement_t net, unsigned ind)
break;
}
case IVL_ST_CASSIGN:
fprintf(out, "%*sCONTINUOUS ASSIGN <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
if (ivl_stmt_rval(net))
show_expression(ivl_stmt_rval(net), ind+4);
break;
case IVL_ST_CONDIT: {
ivl_expr_t ex = ivl_stmt_cond_expr(net);
ivl_statement_t t = ivl_stmt_cond_true(net);
@ -501,6 +510,15 @@ static void show_statement(ivl_statement_t net, unsigned ind)
break;
}
case IVL_ST_DEASSIGN:
fprintf(out, "%*sDEASSIGN <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
break;
case IVL_ST_DELAY:
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
show_statement(ivl_stmt_sub_stmt(net), ind+2);
@ -656,7 +674,9 @@ static void show_event(ivl_event_t net)
static void show_signal(ivl_signal_t net)
{
unsigned pin;
unsigned idx;
ivl_nexus_t nex;
const char*type = "?";
const char*port = "";
const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";
@ -702,61 +722,60 @@ static void show_signal(ivl_signal_t net)
break;
}
fprintf(out, " %s %s %s[%u] %s\n", type, sign, port,
ivl_signal_pins(net), ivl_signal_basename(net));
nex = ivl_signal_nex(net);
for (pin = 0 ; pin < ivl_signal_pins(net) ; pin += 1) {
unsigned idx;
ivl_nexus_t nex = ivl_signal_pin(net, pin);
fprintf(out, " [%u]: nexus=%s\n", pin, ivl_nexus_name(nex));
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_net_const_t con;
ivl_net_logic_t log;
ivl_lpm_t lpm;
ivl_signal_t sig;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
static const char* str_tab[8] = {
"HiZ", "small", "medium", "weak",
"large", "pull", "strong", "supply"};
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
if ((sig = ivl_nexus_ptr_sig(ptr))) {
fprintf(out, " %s[%u] (%s0, %s1)\n",
ivl_signal_name(sig),
ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((log = ivl_nexus_ptr_log(ptr))) {
fprintf(out, " %s[%u] (%s0, %s1)\n",
ivl_logic_name(log),
ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
ivl_scope_name(ivl_lpm_scope(lpm)),
ivl_lpm_basename(lpm), dr0, dr1);
} else if ((con = ivl_nexus_ptr_con(ptr))) {
const char*bits = ivl_const_bits(con);
unsigned pin = ivl_nexus_ptr_pin(ptr);
fprintf(out, " const-%c (%s0, %s1)\n",
bits[pin], dr0, dr1);
fprintf(out, " %s %s %s[%d:%d] %s <width=%u> nexus=%s\n",
type, sign, port,
ivl_signal_msb(net), ivl_signal_lsb(net),
ivl_signal_basename(net), ivl_signal_width(net),
ivl_nexus_name(nex));
} else {
fprintf(out, " ?[%u] (%s0, %s1)\n",
ivl_nexus_ptr_pin(ptr), dr0, dr1);
}
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_net_const_t con;
ivl_net_logic_t log;
ivl_lpm_t lpm;
ivl_signal_t sig;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
static const char* str_tab[8] = {
"HiZ", "small", "medium", "weak",
"large", "pull", "strong", "supply"};
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
if ((sig = ivl_nexus_ptr_sig(ptr))) {
fprintf(out, " %s[%u] (%s0, %s1)\n",
ivl_signal_name(sig),
ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((log = ivl_nexus_ptr_log(ptr))) {
fprintf(out, " %s[%u] (%s0, %s1)\n",
ivl_logic_name(log),
ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
ivl_scope_name(ivl_lpm_scope(lpm)),
ivl_lpm_basename(lpm), dr0, dr1);
} else if ((con = ivl_nexus_ptr_con(ptr))) {
const char*bits = ivl_const_bits(con);
unsigned pin = ivl_nexus_ptr_pin(ptr);
fprintf(out, " const-%c (%s0, %s1)\n",
bits[pin], dr0, dr1);
} else {
fprintf(out, " ?[%u] (%s0, %s1)\n",
ivl_nexus_ptr_pin(ptr), dr0, dr1);
}
}
for (pin = 0 ; pin < ivl_signal_attr_cnt(net) ; pin += 1) {
ivl_attribute_t atr = ivl_signal_attr_val(net, pin);
for (idx = 0 ; idx < ivl_signal_attr_cnt(net) ; idx += 1) {
ivl_attribute_t atr = ivl_signal_attr_val(net, idx);
switch (atr->type) {
case IVL_ATT_STR:
@ -837,7 +856,7 @@ static void show_logic(ivl_net_logic_t net)
fprintf(out, ", %s", ivl_nexus_name(nex));
}
fprintf(out, ");\n");
fprintf(out, "); <width=%u>\n", ivl_logic_width(net));
npins = ivl_logic_attr_cnt(net);
for (idx = 0 ; idx < npins ; idx += 1) {
@ -953,6 +972,11 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.91 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.90 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_vpi.c,v 1.9 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: draw_vpi.c,v 1.10 2004/12/11 02:31:28 steve Exp $"
#endif
# include "vvp_priv.h"
@ -89,6 +89,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
break;
case IVL_EX_SIGNAL:
#if 0
/* If the signal node is narrower then the signal
itself, then this is a part select so I'm going
to need to evaluate the expression.
@ -112,7 +113,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
} else {
continue;
}
#else
continue;
#endif
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
@ -169,6 +172,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
/* If this is a part select, then the value was
calculated above. Otherwise, just pass the
signal. */
#if 0
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
break;
@ -182,6 +186,11 @@ static void draw_vpi_taskfunc_args(const char*call_string,
vvp_signal_label(ivl_expr_signal(expr)));
continue;
}
#else
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
continue;
#endif
case IVL_EX_VARIABLE: {
ivl_variable_t var = ivl_expr_variable(expr);
@ -296,6 +305,11 @@ int draw_vpi_rfunc_call(ivl_expr_t fnet)
/*
* $Log: draw_vpi.c,v $
* Revision 1.10 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.9 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.110 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: eval_expr.c,v 1.111 2004/12/11 02:31:28 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1464,22 +1464,12 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
if (swid > res.wid)
swid = res.wid;
if (ivl_signal_type(sig) == IVL_SIT_REG) {
/* If this is a REG (a variable) then I can do a vector
read. */
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
res.base, vvp_signal_label(sig), lsi, swid);
} else {
/* Vector reads of nets do not in general work because
they are not really functors but references to
scattered functors. So generate an array of loads. */
for (idx = 0 ; idx < swid ; idx += 1) {
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx, vvp_signal_label(sig), idx+lsi);
}
}
/* XXXX I forget how to do part selects here. */
assert(lsi == 0);
/* If this is a REG (a variable) then I can do a vector read. */
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(sig), swid);
/* Pad the signal value with zeros. */
if (swid < res.wid) {
@ -2139,6 +2129,11 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.111 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.110 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_priv.h,v 1.28 2004/01/20 21:00:47 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.29 2004/12/11 02:31:28 steve Exp $"
#endif
# include "vvp_config.h"
@ -138,7 +138,7 @@ extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
* Return the base of an allocated vector in the thread. The bits
* are marked allocated in the process.
*
* clr_bector
* clr_vector
* Clear a vector previously allocated.
*
* The thread vector allocator also keeps a lookaside of expression
@ -193,6 +193,11 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.29 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.28 2004/01/20 21:00:47 steve
* Isolate configure from containing config.h
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_process.c,v 1.93 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: vvp_process.c,v 1.94 2004/12/11 02:31:28 steve Exp $"
#endif
# include "vvp_priv.h"
@ -77,6 +77,9 @@ static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
ivl_signal_t sig = ivl_lval_sig(lval);
unsigned part_off = ivl_lval_part_off(lval);
assert(idx == 0);
assert(part_off == 0); // XXXX Forgot how to support part/bit writes.
if (ivl_lval_mux(lval)) {
assert(wid == 1);
if ((ivl_signal_pins(sig)-1) <= 0xffffU) {
@ -92,13 +95,9 @@ static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
vvp_signal_label(sig), bit);
}
} else if (wid == 1) {
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
vvp_signal_label(sig), idx+part_off, bit);
} else {
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n",
vvp_signal_label(sig), idx+part_off, bit, wid);
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(sig), bit, wid);
}
}
@ -142,9 +141,12 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned idx,
unsigned part_off = ivl_lval_part_off(lval);
assert(ivl_lval_mux(lval) == 0);
assert(part_off == 0);
assert(idx == 0);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n",
vvp_signal_label(sig), part_off+idx, delay, bit);
fprintf(vvp_out, " %%assign/v0 V_%s, %u, %u;\n",
vvp_signal_label(sig), delay, bit);
}
@ -212,8 +214,8 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
skip_set_flag = 1;
}
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
@ -223,10 +225,12 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
set_to_memory(mem, idx, bidx);
cur_rbit += 1;
}
#if 0
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
set_to_memory(mem, idx, 0);
#else
assert(0);
#endif
} else {
unsigned bidx = res.base < 4
@ -234,11 +238,6 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
: (res.base+cur_rbit);
set_to_lvariable(lval, 0, bidx, bit_limit);
cur_rbit += bit_limit;
if (bit_limit < ivl_lval_pins(lval)) {
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
set_to_lvariable(lval, bit_limit, 0, cnt);
}
}
@ -317,8 +316,8 @@ static int show_stmt_assign_vector(ivl_statement_t net)
skip_set_flag = 1;
}
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
@ -329,11 +328,28 @@ static int show_stmt_assign_vector(ivl_statement_t net)
}
for (idx = bit_limit
; idx < ivl_lval_pins(lval) ; idx += 1)
; idx < ivl_lval_width(lval) ; idx += 1)
set_to_memory(mem, idx, 0);
} else {
/* Here we have the case of a blocking
assign of a number to a signal:
<sig> = NUMBER;
Collect the number value into thread
bits, and use a %set/v to write the reg
variable. */
ivl_signal_t sig = ivl_lval_sig(lval);
struct vector_info vect;
vect.wid = ivl_lval_width(lval);
vect.base = allocate_vector(vect.wid);
/* This loop makes the value into thread
bits. Use the constant thread bits 0-3 to
generate the values of the vector. */
idx = 0;
while (idx < bit_limit) {
unsigned cnt = 1;
@ -341,19 +357,19 @@ static int show_stmt_assign_vector(ivl_statement_t net)
&& (bits[cur_rbit] == bits[cur_rbit+cnt]))
cnt += 1;
set_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
cnt);
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
vect.base+idx,
bitchar_to_idx(bits[cur_rbit]),
cnt);
cur_rbit += cnt;
idx += cnt;
}
if (bit_limit < ivl_lval_pins(lval)) {
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
set_to_lvariable(lval, bit_limit, 0, cnt);
}
/* write out the value into the .var. */
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(sig), vect.base, vect.wid);
clr_vector(vect);
}
if (skip_set_flag) {
@ -490,138 +506,6 @@ static int show_stmt_assign_nb(ivl_statement_t net)
del = 0;
}
/* Handle the special case that the r-value is a constant. We
can generate the %set statement directly, without any worry
about generating code to evaluate the r-value expressions. */
if (ivl_expr_type(rval) == IVL_EX_NUMBER) {
unsigned lidx;
const char*bits = ivl_expr_bits(rval);
unsigned wid = ivl_expr_width(rval);
unsigned cur_rbit = 0;
if (del != 0)
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)) {
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) {
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);
if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
assign_to_memory(mem, idx,
bitchar_to_idx(bits[cur_rbit]),
delay);
cur_rbit += 1;
}
for (idx = bit_limit
; idx < ivl_lval_pins(lval)
; idx += 1) {
assign_to_memory(mem, idx, 0, delay);
}
} else if ((del == 0) && (bit_limit > 2)) {
/* We have a vector, but no runtime
calculated delays, to try to use vector
assign instructions. */
idx = 0;
while (idx < bit_limit) {
unsigned wid = 0;
do {
wid += 1;
if ((idx + wid) == bit_limit)
break;
} while (bits[cur_rbit] == bits[cur_rbit+wid]);
switch (wid) {
case 1:
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
break;
case 2:
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
assign_to_lvariable(lval, idx+1,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
break;
default:
assign_to_lvector(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, wid);
break;
}
idx += wid;
cur_rbit += wid;
}
if (bit_limit < ivl_lval_pins(lval)) {
unsigned wid = ivl_lval_pins(lval) - bit_limit;
assign_to_lvector(lval, bit_limit,
0, delay, wid);
}
} 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);
}
}
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, 0);
unsigned wid = res.wid;
@ -653,10 +537,10 @@ static int show_stmt_assign_nb(ivl_statement_t net)
skip_set_flag = 1;
}
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
if ((bit_limit > 2) && (mem == 0) && (del == 0)) {
if ((mem == 0) && (del == 0)) {
unsigned bidx = res.base < 4
? res.base
@ -682,7 +566,7 @@ static int show_stmt_assign_nb(ivl_statement_t net)
}
}
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
for (idx = bit_limit; idx < ivl_lval_width(lval); idx += 1)
if (mem)
assign_to_memory(mem, idx, 0, delay);
else if (del != 0)
@ -939,8 +823,7 @@ static int show_stmt_cassign(ivl_statement_t net)
{
ivl_lval_t lval;
ivl_signal_t lsig;
unsigned idx;
char*tmp_label;
ivl_expr_t rval;
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
@ -948,16 +831,22 @@ static int show_stmt_cassign(ivl_statement_t net)
lsig = ivl_lval_sig(lval);
assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0);
assert(ivl_signal_pins(lsig) == ivl_stmt_nexus_count(net));
assert(ivl_lval_part_off(lval) == 0);
tmp_label = strdup(vvp_signal_label(lsig));
for (idx = 0 ; idx < ivl_stmt_nexus_count(net) ; idx += 1) {
fprintf(vvp_out, " %%cassign V_%s[%u], %s;\n",
tmp_label, idx,
draw_net_input(ivl_stmt_nexus(net, idx)));
if ( (rval = ivl_stmt_rval(net)) ) {
struct vector_info rvec = draw_eval_expr(rval, STUFF_OK_47);
fprintf(vvp_out, " %%cassign/v V_%s, %u, %u;\n",
vvp_signal_label(lsig), rvec.base, rvec.wid);
} else {
/* The statement nexus count is an obsolete concept.
Should be 1. */
assert(ivl_stmt_nexus_count(net) == 1);
fprintf(stderr, "XXXX tgt-vvp: forgot how to implement cassign\n");
return -1;
}
free(tmp_label);
return 0;
}
@ -976,10 +865,8 @@ static int show_stmt_deassign(ivl_statement_t net)
assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0);
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
fprintf(vvp_out, " %%deassign V_%s[%u], 1;\n",
vvp_signal_label(lsig), idx);
}
fprintf(vvp_out, " %%deassign V_%s;\n", vvp_signal_label(lsig));
return 0;
}
@ -1113,7 +1000,7 @@ static int show_stmt_force(ivl_statement_t net)
assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0);
#if 0
force_functor_label += 1;
tmp_label = strdup(vvp_signal_label(lsig));
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
@ -1128,6 +1015,9 @@ static int show_stmt_force(ivl_statement_t net)
fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
force_functor_label, idx);
}
#else
fprintf(stderr, "XXXX I forgot how to implement %%force\n");
#endif
return 0;
}
@ -1222,7 +1112,7 @@ static int show_stmt_release(ivl_statement_t net)
done before we start. */
if (ivl_stmt_lvals(net) == 0)
return 0;
#if 0
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
@ -1243,7 +1133,9 @@ static int show_stmt_release(ivl_statement_t net)
fprintf(vvp_out, " %%release V_%s[%u];\n",
vvp_signal_label(lsig), idx);
}
#else
fprintf(stderr, "XXXX I forgot how to implement %%release\n");
#endif
return 0;
}
@ -1626,6 +1518,11 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.94 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.93 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.103 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.104 2004/12/11 02:31:29 steve Exp $"
#endif
# include "vvp_priv.h"
@ -350,33 +350,53 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
sptr = ivl_nexus_ptr_sig(nptr);
if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
sprintf(result, "V_%s[%u]", vvp_signal_label(sptr), nptr_pin);
/* Input is a .var. Note that these devices have only
exactly one pin (that carries a vector) so nptr_pin
must be 0. */
assert(nptr_pin == 0);
sprintf(result, "V_%s", vvp_signal_label(sptr));
return result;
}
cptr = ivl_nexus_ptr_con(nptr);
if (cptr) {
/* Constants should have exactly 1 pin, with a vector
result. */
assert(nptr_pin == 0);
const char*bits = ivl_const_bits(cptr);
ivl_drive_t drive;
switch (bits[nptr_pin]) {
case '0':
drive = ivl_nexus_ptr_drive0(nptr);
if (drive == IVL_DR_HiZ)
sprintf(result, "C<z>");
else
sprintf(result, "C<%s0>", drive_string(drive));
break;
case '1':
drive = ivl_nexus_ptr_drive1(nptr);
if (drive == IVL_DR_HiZ)
sprintf(result, "C<z>");
else
sprintf(result, "C<%s1>", drive_string(drive));
break;
default:
sprintf(result, "C<%c>", bits[nptr_pin]);
unsigned idx;
char*dp = result;
strcpy(dp, "C4<");
dp += strlen(dp);
for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
switch (bits[ivl_const_width(cptr)-idx-1]) {
case '0':
drive = ivl_nexus_ptr_drive0(nptr);
if (drive == IVL_DR_HiZ) {
*dp++ = 'z';
} else {
*dp++ = '0';
}
break;
case '1':
drive = ivl_nexus_ptr_drive1(nptr);
if (drive == IVL_DR_HiZ) {
*dp++ = 'z';
} else {
*dp++ = '1';
}
break;
default:
*dp++ = bits[idx];
break;
}
assert(dp - result < sizeof result);
}
strcpy(dp, ">");
return result;
}
@ -403,11 +423,11 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_UFUNC:
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
if (ivl_lpm_q(lpm, idx) == nex) {
sprintf(result, "L_%p[%u]", lpm, idx);
return result;
}
case IVL_LPM_PART:
if (ivl_lpm_q(lpm, 0) == nex) {
sprintf(result, "L_%p", lpm);
return result;
}
break;
@ -520,13 +540,13 @@ const char* draw_net_input(ivl_nexus_t nex)
if (ndrivers == 0) {
switch (res) {
case IVL_SIT_TRI:
nex_private = "C<z>";
nex_private = "C4<z>";
break;
case IVL_SIT_TRI0:
nex_private = "C<0>";
nex_private = "C4<0>";
break;
case IVL_SIT_TRI1:
nex_private = "C<1>";
nex_private = "C4<1>";
break;
default:
assert(0);
@ -566,7 +586,7 @@ const char* draw_net_input(ivl_nexus_t nex)
}
}
for ( ; idx < inst+4 ; idx += 1)
fprintf(vvp_out, ", C<z>");
fprintf(vvp_out, ", C4<z>");
fprintf(vvp_out, ";\n");
}
@ -623,11 +643,10 @@ static void draw_reg_in_scope(ivl_signal_t sig)
*/
static void draw_net_in_scope(ivl_signal_t sig)
{
unsigned idx;
int msb = ivl_signal_msb(sig);
int lsb = ivl_signal_lsb(sig);
typedef const char*const_charp;
const_charp* args;
const char* arg;
const char*signed_flag = ivl_signal_signed(sig)? "/s" : "";
@ -635,24 +654,16 @@ static void draw_net_in_scope(ivl_signal_t sig)
if (ivl_signal_local(sig))
return;
args = (const_charp*)calloc(ivl_signal_pins(sig), sizeof(char*));
/* Connect all the pins of the signal to something. */
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
ivl_nexus_t nex = ivl_signal_pin(sig, idx);
args[idx] = draw_net_input(nex);
/* Connect the pin of the signal to something. */
{
ivl_nexus_t nex = ivl_signal_nex(sig);
arg = draw_net_input(nex);
}
fprintf(vvp_out, "V_%s .net%s \"%s\", %d, %d",
fprintf(vvp_out, "V_%s .net%s \"%s\", %d, %d, %s;\n",
vvp_signal_label(sig), signed_flag,
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
fprintf(vvp_out, ", %s", args[idx]);
}
fprintf(vvp_out, ";\n");
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb, arg);
free(args);
}
static void draw_delay(ivl_net_logic_t lptr)
@ -939,7 +950,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
}
}
for ( ; pdx < inst+4 ; pdx += 1) {
fprintf(vvp_out, ", C<%c>", identity_val);
fprintf(vvp_out, ", C4<%c>", identity_val);
}
fprintf(vvp_out, ";\n");
@ -1137,25 +1148,35 @@ static void draw_lpm_arith_a_b_inputs(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned idx;
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t a = ivl_lpm_data(net, idx);
if (a) {
fprintf(vvp_out, ", ");
draw_input_from_net(a);
} else {
fprintf(vvp_out, ", C<0>");
}
assert(width > 0);
ivl_nexus_t nex = ivl_lpm_data(net, 0);
ivl_signal_t sig = 0;
ivl_nexus_ptr_t np;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
np = ivl_nexus_ptr(nex,idx);
sig = ivl_nexus_ptr_sig(np);
if (sig != 0)
break;
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t b = ivl_lpm_datab(net, idx);
if (b) {
fprintf(vvp_out, ", ");
draw_input_from_net(b);
} else {
fprintf(vvp_out, ", C<0>");
}
assert(sig != 0);
fprintf(vvp_out, ", V_%s", vvp_signal_label(sig));
sig = 0;
nex = ivl_lpm_datab(net, 0);
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
np = ivl_nexus_ptr(nex,idx);
sig = ivl_nexus_ptr_sig(np);
if (sig != 0)
break;
}
assert(sig != 0);
fprintf(vvp_out, ", V_%s", vvp_signal_label(sig));
}
static void draw_lpm_add(ivl_lpm_t net)
@ -1458,6 +1479,22 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
fprintf(vvp_out, ";\n");
}
/*
* Handle a PART SELECT device. This has a single input and output.
*/
static void draw_lpm_part(ivl_lpm_t net)
{
unsigned width, base;
width = ivl_lpm_width(net);
base = ivl_lpm_base(net);
fprintf(vvp_out, "L_%p .part ", net);
draw_input_from_net(ivl_lpm_data(net, 0));
fprintf(vvp_out, ", %u, %u;\n", base, width);
}
static void draw_lpm_in_scope(ivl_lpm_t net)
{
switch (ivl_lpm_type(net)) {
@ -1474,6 +1511,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_add(net);
return;
case IVL_LPM_PART:
draw_lpm_part(net);
return;
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE:
draw_lpm_eq(net);
@ -1624,6 +1665,11 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.104 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.103 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.61 2004/10/04 01:09:52 steve Exp $"
#ident "$Id: Makefile.in,v 1.62 2004/12/11 02:31:29 steve Exp $"
#
#
SHELL = /bin/sh
@ -82,9 +82,10 @@ vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
vpip_to_dec.o vpip_format.o vvp_vpi.o
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o \
functor.o fvectors.o npmos.o resolv.o stop.o symbols.o ufunc.o codes.o \
vthread.o schedule.o statistics.o tables.o udp.o memory.o force.o event.o \
logic.o delay.o words.o $V
functor.o fvectors.o npmos.o part.o resolv.o stop.o symbols.o ufunc.o \
codes.o \
vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \
force.o event.o logic.o delay.o words.o $V
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.47 2004/10/04 01:10:58 steve Exp $
* $Id: README.txt,v 1.48 2004/12/11 02:31:29 steve Exp $
*/
VVP SIMULATION ENGINE
@ -241,31 +241,19 @@ A variable does not take inputs, since its value is set behaviorally
by assignment events. It does have output, though, and its output is
propagated into the net of functors in the usual way.
Therefore, the .var statement implicitly also creates .functors
addressed by the label of the variable. It is in fact the functors
that behavioral code reads when the value of the variable (or net) is
read by behavioral code. If the .var represents a vector of .functors,
the index of the LSB is always, from the perspective of vvp, ZERO. The
<msb>,<lsb> details are there only for the benefit of VPI support.
A variable gets its value by assignments from procedural code: %set
and %assign. These instructions write values to the port-0 input. From
there, the value is held.
The variable .functor implicitly has two inputs. The first is the
value that gets set by assignments. The second input is connected to
the driving expression of a procedural continuous assignments.
Variable functors have an extra internal bit that tells if a
procedural continuous assignment is active. The %cassign opcode
connects and activates the procedural continuous assignment. The
%deassign opcode disconnects and deactivates it.
The variable statement also creates a VPI object of the appropriate
type. See the vpi.txt file for details about that object. The msb and
lsb values are set from the parameters of the .var or .var/s, and the
vpiReg is marked unsigned for .var, or signed for .var/s
Note that nets in a design do not necessarily have a specific functor
or object allocated to them. Nets are just something that behavioral
code can read, so it is enough to give to the behavioral code the
vvp_ipoint_t object of the .functor that drives the net.
Behavioral code can also invoke %cassign/v statements that work like
%set/v, but instead write to port-1 of the variable node. Writes to
port-1 of a variable activate continuous assign mode, where the values
written to port-0 are ignored. The continuous assign mode remains
active until a long(1) is written to port-3 (a command port).
Behavioral code may also invoke %force/v statements that write to port-2
to invoke force mode. This overrides continuous assign mode until a
long(2) is written to port-3 to disable force mode.
NET STATEMENTS:
@ -274,14 +262,21 @@ it (unless it uses a force) and it is given a different VPI type
code. The syntax of a .net statement is also similar to but not
exactly the same as the .var statement:
<label> .net "name", <msb>, <lsb>, <symbols_list>;
<label> .net/s "name", <msb>, <lsb>, <symbols_list>;
<label> .net "name", <msb>, <lsb>, <symbol>;
<label> .net/s "name", <msb>, <lsb>, <symbol>;
Like a .var statement, the .net statement creates a VPI object with
the basename and dimensions given as parameters, but unlike a .var
statement, it creates no functors. The symbol list is a list of
functors that feed into each bit of the vector, and the vpiHandle
holds references to those functors that are fed it.
the basename and dimensions given as parameters. The symbol is a
functor that feeds into the vector of the net, and the vpiHandle
holds references to that functor.
NOTE: Nets also, unlike .vars, should also have a way of getting
at the strengths of each bit. I haven't worked out how that will
happen, yet.
The input of a .net is replicated to its output. In this sense, it
acts like a diode. The purpose of this node is to hold various VPI
and event trappings.
The <label> is required and is used to locate the net object that is
represents. This label does not map to a functor, so only references
@ -443,7 +438,19 @@ resolution function.
<label> .resolv tri1, <symbols_list>;
FORCE STATEMENTS:
PART SELECT STATEMENTS:
Part select statements are functors with three inputs. They take in at
port-0 a vector, and output a selected (likely smaller) part of that
vector. The other inputs specify what those parts are, as a cannonical
bit number, and a width. Normally, those bits are constant values.
<label> .part <symbol>, <base>, <wid>;
The input is typically a .reg or .net, but can be any vector node in
the netlist.
FORCE STATEMENTS (old method - remove me):
A force statement creates functors that represent a Verilog force
statement.
@ -465,33 +472,44 @@ To activate and deactivate a force on a single bit, use:
<signal> is the label of the functor that drives the signal that is
being forced.
FORCE STATEMENTS (new method - implement me):
A %force instruction, as described in the .var section, forces a
constant value onto a .var or .net, and the matching %release release
that value. However, there are times when the value of a functor
(i.e. another .net) needs to be forced onto a .var or .net. For this
task, the %force/link instruction exists:
%force/link <dst>, <src> ;
%release/link <dst> ;
This causes the output of the node <src> to be linked to the force
input of the <dst> .var/.net node. When linked, the output functor
will automatically drive values to the force port of the destination
node. The matching %release/link instruction removes the link (a
%release is still needed) to the destination.
The instructions:
%cassign/link <dst>, <src> ;
%deassign/link <dst> ;
are the same concept, but for the continuous assign port.
STRUCTURAL ARITHMETIC STATEMENTS:
The various Verilog arithmetic operators (+-*/%) are available to
structural contexts even though they do not fit into nice neat
functors. These operators are not in general bitwise, so special
measures are needed to make them work in a functor environment. We
create special statement types for the various arithmetic operators.
The various Verilog arithmetic operators (+-*/%) ar avaiable to
structural contexts as two-input functors that take in vectors. All of
these operators take two inputs and generate a fixed width output. The
input vectors will be padded if needed to get the desired output width.
<label> .arith/sub <wid>, <symbols_list>;
<label> .arith/sum <wid>, <symbols_list>;
<label> .arith/mult <wid>, <symbols_list>;
<label> .arith/div <wid>, <symbols_list>;
<label> .arith/mod <wid>, <symbols_list>;
Addition is represented by the .arith/sum statement. This creates an
array of functors based at the label. The width of the array is given
by <wid>, and the <symbols_list> connects the inputs.
The sum can add together up to 4 operands, specified in the
<symbols_list> one bit at a time. All the bits of the first operand
(lsb first) are listed, then the bits of the second, and so on. The
number of symbols must be an even multiple of the width of the operator.
Subtraction is similar to addition, except that the 2nd, 3rd and 4th
vectors are subtracted from the first.
<label> .arith/sub <wid>, <A>, <B>;
<label> .arith/sum <wid>, <A>, <B>;
<label> .arith/mult <wid>, <A>, <B>;
<label> .arith/div <wid>, <A>, <B>;
<label> .arith/mod <wid>, <A>, <B>;
In all cases, there are no width limits, so long as the width is fixed.
STRUCTURAL COMPARE STATEMENTS:
@ -587,6 +605,23 @@ parent, and %end in the child. Without this proper matching, the
hierarchical relationships can get confused. The behavior of erroneous
code is undefined.
* Thread Context
The context of a thread is all the local data that only that thread
can address. The local data is broken into two addresses spaces: bit
memory and word memory.
The bit memory is a region of 4-value bits (0,1,x,z) that can be
addressed in strips of arbitrary length. For example, an 8-bit value
can be in locations 8 through and including 15. The bits at address 0,
1, 2 and 3 are special constant values. Reads from those locations
make vectors of 0, 1, x or z values, so these can be used to
manufacture complex values elsewhere.
The word memory is a region of tagged words. The value in each word
may be native long or real. These words have a distinct address space
from the bits.
* Threads and scopes
The Verilog ``disable'' statement deserves some special mention

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: arith.cc,v 1.30 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: arith.cc,v 1.31 2004/12/11 02:31:29 steve Exp $"
#endif
# include "arith.h"
@ -30,57 +30,11 @@
# include <malloc.h>
#endif
void vvp_arith_::output_x_(vvp_ipoint_t base, bool push, unsigned val)
vvp_arith_::vvp_arith_(unsigned wid)
: wid_(wid), x_val_(wid)
{
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
obj->put_oval(val, push);
}
}
void vvp_arith_::output_val_(vvp_ipoint_t base, bool push, unsigned long sum)
{
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
unsigned val = sum & 1;
sum >>= 1;
obj->put_oval(val, push);
}
}
// Make sure the static sum_ scratch space is large enough for everybody
vvp_wide_arith_::vvp_wide_arith_(unsigned wid)
: vvp_arith_(wid)
{
pagecount_ = (wid + pagesize - 1)/pagesize;
sum_ = (unsigned long *)calloc(pagecount_, sizeof(unsigned long));
assert(sum_);
}
void vvp_wide_arith_::output_val_(vvp_ipoint_t base, bool push)
{
unsigned page = 0;
unsigned pbit = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
unsigned val = (sum_[page] >> pbit) & 1;
pbit += 1;
if (pbit == pagesize) {
pbit = 0;
page += 1;
}
obj->put_oval(val, push);
}
for (unsigned idx = 0 ; idx < wid ; idx += 1)
x_val_.set_bit(idx, BIT4_X);
}
@ -94,6 +48,7 @@ inline void vvp_arith_div::wide(vvp_ipoint_t base, bool push)
void vvp_arith_div::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
#if 0
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
@ -146,6 +101,9 @@ void vvp_arith_div::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
result = 0 - result;
output_val_(base, push, result);
#else
fprintf(stderr, "XXXX forgot how to implement vvp_arith_div::set\n");
#endif
}
inline void vvp_arith_mod::wide(vvp_ipoint_t base, bool push)
@ -155,6 +113,7 @@ inline void vvp_arith_mod::wide(vvp_ipoint_t base, bool push)
void vvp_arith_mod::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
#if 0
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
@ -187,12 +146,16 @@ void vvp_arith_mod::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
}
output_val_(base, push, a%b);
#else
fprintf(stderr, "XXXX forgot how to implement vvp_arith_mod::set\n");
#endif
}
// Multiplication
void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
#if 0
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
@ -220,8 +183,12 @@ void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
}
output_val_(base, push, a*b);
#else
fprintf(stderr, "XXXX forgot how to implement vvp_arith_mult::set\n");
#endif
}
#if 0
void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
{
unsigned char *a, *b, *sum;
@ -284,62 +251,67 @@ void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
delete[]b;
delete[]a;
}
#endif
// Addition
void vvp_arith_sum::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
vvp_arith_sum::vvp_arith_sum(unsigned wid)
: vvp_arith_(wid)
{
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
}
unsigned page = 0;
unsigned pbit = 0;
unsigned long carry = 0;
vvp_arith_sum::~vvp_arith_sum()
{
}
sum_[0] = 0;
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
{
unsigned port = ptr.port();
switch (port) {
case 0:
op_a_ = bit;
break;
case 1:
op_b_ = bit;
break;
default:
assert(0);
}
vvp_net_t*net = ptr.ptr();
vvp_vector4_t value (wid_);
/* Pad input vectors with this value to widen to the desired
output width. */
const vvp_bit4_t pad = BIT4_0;
vvp_bit4_t carry = BIT4_0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t obj = functor_index(ptr);
vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
vvp_bit4_t b = (idx >= op_b_.size())? pad : op_b_.value(idx);
vvp_bit4_t cur = add_with_carry(a, b, carry);
unsigned val = obj->ival;
if (val & 0xaa) {
output_x_(base, push);
if (cur == BIT4_X) {
vvp_send_vec4(net->out, x_val_);
return;
}
// Accumulate the sum of the input bits.
unsigned long tmp = 0;
if (val & 0x01)
tmp += 1;
if (val & 0x04)
tmp += 1;
if (val & 0x10)
tmp += 1;
if (val & 0x40)
tmp += 1;
// Save carry bits
if (pbit >= pagesize - 2)
carry += (tmp + (sum_[page]>>pbit)) >> (pagesize-pbit);
// Put the next bits into the sum,
sum_[page] += tmp << pbit;
pbit += 1;
if (pbit >= pagesize) {
pbit = 0;
page += 1;
if (page < pagecount_)
sum_[page] = carry;
carry = 0;
}
value.set_bit(idx, cur);
}
output_val_(base, push);
vvp_send_vec4(net->out, value);
}
vvp_arith_sub::vvp_arith_sub(unsigned wid)
: vvp_arith_(wid)
{
}
vvp_arith_sub::~vvp_arith_sub()
{
}
/*
* Subtraction works by adding the 2s complement of the B, C and D
@ -347,67 +319,54 @@ void vvp_arith_sum::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
* plus one, so we further reduce the operation to adding in the
* inverted value and adding a correction.
*/
void vvp_arith_sub::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
{
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned port = ptr.port();
unsigned page = 0;
unsigned pbit = 0;
unsigned long carry = 0;
switch (port) {
case 0:
op_a_ = bit;
break;
case 1:
op_b_ = bit;
break;
default:
assert(0);
}
/* There are 3 values subtracted from the first parameter, so
there are three 2s complements, so three ~X +1. That's why
the sum_ starts with 3. */
sum_[0] = 3;
vvp_net_t*net = ptr.ptr();
vvp_vector4_t value (wid_);
/* Pad input vectors with this value to widen to the desired
output width. */
const vvp_bit4_t pad = BIT4_1;
vvp_bit4_t carry = BIT4_1;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t obj = functor_index(ptr);
vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
vvp_bit4_t b = (idx >= op_b_.size())? pad : op_b_.value(idx);
vvp_bit4_t cur = add_with_carry(a, b, carry);
unsigned val = obj->ival;
if (val & 0xaa) {
output_x_(base, push);
if (cur == BIT4_X) {
vvp_send_vec4(net->out, x_val_);
return;
}
// Accumulate the sum of the input bits. Add in the
// first value, and the ones complement of the other values.
unsigned long tmp = 0;
if (val & 0x01)
tmp += 1;
if (! (val & 0x04))
tmp += 1;
if (! (val & 0x10))
tmp += 1;
if (! (val & 0x40))
tmp += 1;
// Save carry bits
if (pbit >= pagesize - 2)
carry += (tmp + (sum_[page]>>pbit)) >> (pagesize-pbit);
// Put the next bits into the sum,
sum_[page] += tmp << pbit;
pbit += 1;
if (pbit >= pagesize) {
pbit = 0;
page += 1;
if (page < pagecount_)
sum_[page] = carry;
carry = 0;
}
value.set_bit(idx, cur);
}
output_val_(base, push);
vvp_send_vec4(net->out, value);
}
vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
: vvp_arith_(wid)
{
}
#if 0
void vvp_cmp_eq::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
put(i, val);
@ -436,12 +395,14 @@ void vvp_cmp_eq::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
put_oval(out_val, push);
}
#endif
vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
: vvp_arith_(wid)
{
}
#if 0
void vvp_cmp_ne::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
put(i, val);
@ -470,14 +431,14 @@ void vvp_cmp_ne::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
put_oval(out_val, push);
}
#endif
vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid, bool flag)
: vvp_arith_(wid), signed_flag_(flag)
{
}
#if 0
void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i,
bool push,
unsigned val,
@ -561,7 +522,7 @@ void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i,
put_oval(out_val, push);
}
#endif
vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
@ -570,22 +531,26 @@ vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
}
#if 0
void vvp_cmp_ge::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str)
{
set_base(i, push, val, str, 1);
}
#endif
vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
: vvp_cmp_gtge_base_(wid, flag)
{
}
#if 0
void vvp_cmp_gt::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str)
{
set_base(i, push, val, str, 0);
}
#endif
#if 0
void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
put(i, val);
@ -634,7 +599,9 @@ void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
}
}
}
#endif
#if 0
void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
put(i, val);
@ -683,91 +650,14 @@ void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
}
}
}
#endif
/*
* $Log: arith.cc,v $
* Revision 1.30 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
* Revision 1.31 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.29 2004/09/22 16:44:07 steve
* Fix LPM GE to match LPM GT behavior.
*
* Revision 1.28 2004/06/30 02:15:57 steve
* Add signed LPM divide.
*
* Revision 1.27 2004/06/16 16:33:26 steve
* Add structural equality compare nodes.
*
* Revision 1.26 2003/08/01 00:58:34 steve
* Fix arithmetic operators in 64bit processors.
*
* Revision 1.25 2003/04/11 05:15:38 steve
* Add signed versions of .cmp/gt/ge
*
* Revision 1.24 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.23 2002/05/07 04:15:43 steve
* Fix uninitialized memory accesses.
*
* Revision 1.22 2002/01/03 04:19:02 steve
* Add structural modulus support down to vvp.
*
* Revision 1.21 2001/12/06 03:31:24 steve
* Support functor delays for gates and UDP devices.
* (Stephan Boettcher)
*
* Revision 1.20 2001/11/07 03:34:41 steve
* Use functor pointers where vvp_ipoint_t is unneeded.
*
* Revision 1.19 2001/11/04 05:03:21 steve
* MacOSX 10.1 updates.
*
* Revision 1.18 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.17 2001/10/27 03:22:26 steve
* Minor rework of summation carry propagation (Stephan Boettcher)
*
* Revision 1.16 2001/10/16 03:10:20 steve
* Get Division error into the division method!
*
* Revision 1.15 2001/10/16 03:06:18 steve
* Catch division by zero in .arith/div.
*
* Revision 1.14 2001/10/16 02:47:37 steve
* Add arith/div object.
*
* Revision 1.13 2001/10/14 17:36:18 steve
* Forgot to propagate carry.
*
* Revision 1.12 2001/10/14 16:36:43 steve
* Very wide multiplication (Anthony Bybell)
*
* Revision 1.11 2001/07/13 00:38:57 steve
* Remove width restriction on subtraction.
*
* Revision 1.10 2001/07/11 02:27:21 steve
* Add support for REadOnlySync and monitors.
*
* Revision 1.9 2001/07/07 02:57:33 steve
* Add the .shift/r functor.
*
* Revision 1.8 2001/07/06 04:46:44 steve
* Add structural left shift (.shift/l)
*
* Revision 1.7 2001/06/29 01:21:48 steve
* Relax limit on width of structural sum.
*
* Revision 1.6 2001/06/29 01:20:20 steve
* Relax limit on width of structural sum.
*
* Revision 1.5 2001/06/16 23:45:05 steve
* Add support for structural multiply in t-dll.
* Add code generators and vvp support for both
* structural and behavioral multiply.
*/

View File

@ -19,38 +19,26 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: arith.h,v 1.19 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: arith.h,v 1.20 2004/12/11 02:31:29 steve Exp $"
#endif
# include "functor.h"
# include "vvp_net.h"
// base class for arithmetic functors
class vvp_arith_ : public functor_s {
class vvp_arith_ : public vvp_net_fun_t {
public:
explicit vvp_arith_(unsigned wid) : wid_(wid) {};
explicit vvp_arith_(unsigned wid);
protected:
unsigned wid_;
protected:
void output_x_(vvp_ipoint_t base, bool push, unsigned val = 2);
void output_val_(vvp_ipoint_t base, bool push, unsigned long sum);
};
// base class for wide arithmetic functors
class vvp_wide_arith_ : public vvp_arith_ {
public:
explicit vvp_wide_arith_(unsigned wid);
protected:
static const unsigned pagesize = 8*sizeof(unsigned long);
unsigned pagecount_;
unsigned long *sum_;
void output_val_(vvp_ipoint_t base, bool push);
vvp_vector4_t op_a_;
vvp_vector4_t op_b_;
// Precalculated X result for propagation.
vvp_vector4_t x_val_;
};
/*
@ -89,20 +77,26 @@ class vvp_arith_mod : public vvp_arith_ {
void wide(vvp_ipoint_t base, bool push);
};
class vvp_arith_sum : public vvp_wide_arith_ {
class vvp_arith_sum : public vvp_arith_ {
public:
explicit vvp_arith_sum(unsigned wid) : vvp_wide_arith_(wid) {}
explicit vvp_arith_sum(unsigned wid);
~vvp_arith_sum();
public:
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
class vvp_arith_sub : public vvp_wide_arith_ {
class vvp_arith_sub : public vvp_arith_ {
public:
explicit vvp_arith_sub(unsigned wid) : vvp_wide_arith_(wid) {}
explicit vvp_arith_sub(unsigned wid);
~vvp_arith_sub();
public:
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
class vvp_cmp_eq : public vvp_arith_ {
@ -169,66 +163,10 @@ class vvp_shiftr : public vvp_arith_ {
/*
* $Log: arith.h,v $
* Revision 1.19 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
* Revision 1.18 2004/09/22 16:44:07 steve
* Fix LPM GE to match LPM GT behavior.
*
* Revision 1.17 2004/06/30 02:15:57 steve
* Add signed LPM divide.
*
* Revision 1.16 2004/06/16 16:33:26 steve
* Add structural equality compare nodes.
*
* Revision 1.15 2003/04/11 05:15:38 steve
* Add signed versions of .cmp/gt/ge
*
* Revision 1.14 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.13 2002/05/07 04:15:43 steve
* Fix uninitialized memory accesses.
*
* Revision 1.12 2002/01/03 04:19:02 steve
* Add structural modulus support down to vvp.
*
* Revision 1.11 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.10 2001/10/27 03:22:26 steve
* Minor rework of summation carry propagation (Stephan Boettcher)
*
* Revision 1.9 2001/10/16 02:47:37 steve
* Add arith/div object.
*
* Revision 1.8 2001/07/13 00:38:57 steve
* Remove width restriction on subtraction.
*
* Revision 1.7 2001/07/07 02:57:33 steve
* Add the .shift/r functor.
*
* Revision 1.6 2001/07/06 04:46:44 steve
* Add structural left shift (.shift/l)
*
* Revision 1.5 2001/06/29 01:20:20 steve
* Relax limit on width of structural sum.
*
* Revision 1.4 2001/06/16 23:45:05 steve
* Add support for structural multiply in t-dll.
* Add code generators and vvp support for both
* structural and behavioral multiply.
*
* Revision 1.3 2001/06/15 04:07:58 steve
* Add .cmp statements for structural comparison.
*
* Revision 1.2 2001/06/07 03:09:03 steve
* Implement .arith/sub subtraction.
*
* Revision 1.1 2001/06/05 03:05:41 steve
* Add structural addition.
* Revision 1.20 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/
#endif

View File

@ -19,11 +19,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: codes.h,v 1.66 2004/06/19 15:52:53 steve Exp $"
#ident "$Id: codes.h,v 1.67 2004/12/11 02:31:29 steve Exp $"
#endif
# include "pointers.h"
# include "vvp_net.h"
# include "memory.h"
# include "vthread.h"
@ -39,7 +40,6 @@ extern bool of_ADD_WR(vthread_t thr, vvp_code_t code);
extern bool of_ADDI(vthread_t thr, vvp_code_t code);
extern bool of_AND(vthread_t thr, vvp_code_t code);
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
@ -47,7 +47,7 @@ extern bool of_ASSIGN_WR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_BLEND(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code);
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
extern bool of_CMPS(vthread_t thr, vvp_code_t code);
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
@ -78,7 +78,6 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_MEM(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
@ -99,7 +98,6 @@ 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);
extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
extern bool of_SET(vthread_t thr, vvp_code_t code);
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
@ -133,7 +131,7 @@ struct vvp_code_s {
union {
unsigned long number;
vvp_ipoint_t iptr;
vvp_net_t *net;
vvp_code_t cptr;
vvp_memory_t mem;
struct __vpiHandle*handle;
@ -143,7 +141,7 @@ struct vvp_code_s {
union {
unsigned bit_idx[2];
vvp_ipoint_t iptr2;
vvp_net_t *net2;
vvp_code_t cptr2;
struct ufunc_core*ufunc_core_ptr;
};
@ -170,6 +168,11 @@ extern vvp_code_t codespace_null(void);
/*
* $Log: codes.h,v $
* Revision 1.67 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.66 2004/06/19 15:52:53 steve
* Add signed modulus operator.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.175 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: compile.cc,v 1.176 2004/12/11 02:31:29 steve Exp $"
#endif
# include "arith.h"
@ -88,7 +88,6 @@ const static struct opcode_table_s opcode_table[] = {
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
@ -96,7 +95,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cassign",of_CASSIGN,2, {OA_FUNC_PTR, OA_FUNC_PTR2,OA_NONE} },
{ "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
@ -106,7 +105,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%deassign",of_DEASSIGN,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%deassign",of_DEASSIGN,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -125,7 +124,6 @@ const static struct opcode_table_s opcode_table[] = {
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%load/m", of_LOAD_MEM,2, {OA_BIT1, OA_MEM_PTR, OA_NONE} },
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
@ -146,7 +144,6 @@ const static struct opcode_table_s opcode_table[] = {
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%release",of_RELEASE,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/wr", of_SET_WORDR,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
@ -213,21 +210,21 @@ static symbol_table_t sym_vpi = 0;
* Add a functor to the symbol table
*/
void define_functor_symbol(const char*label, vvp_ipoint_t ipt)
void define_functor_symbol(const char*label, vvp_net_t*net)
{
symbol_value_t val;
val.num = ipt;
val.net = net;
sym_set_value(sym_functors, label, val);
}
static vvp_ipoint_t lookup_functor_symbol(const char*label)
static vvp_net_t*lookup_functor_symbol(const char*label)
{
assert(sym_functors);
symbol_value_t val = sym_get_value(sym_functors, label);
return val.num;
return val.net;
}
static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
static vvp_net_t* vvp_net_lookup(const char*label)
{
/* First, look to see if the symbol is a vpi object of some
sort. If it is, then get the vvp_ipoint_t pointer out of
@ -240,7 +237,7 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
case vpiReg:
case vpiIntegerVar: {
__vpiSignal*sig = (__vpiSignal*)vpi;
return vvp_fvector_get(sig->bits, idx);
return sig->node;
}
case vpiNamedEvent: {
@ -253,10 +250,9 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
}
}
/* Failing that, look for a general functor. */
vvp_ipoint_t tmp = lookup_functor_symbol(label);
if (tmp)
tmp = ipoint_index(tmp, idx);
vvp_net_t*tmp = lookup_functor_symbol(label);
return tmp;
}
@ -282,6 +278,7 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
static struct resolv_list_s*resolv_list = 0;
struct resolv_list_s {
virtual ~resolv_list_s() { }
struct resolv_list_s*next;
virtual bool resolve(bool mes = false) = 0;
};
@ -299,63 +296,64 @@ static void resolv_submit(struct resolv_list_s*cur)
/*
* And the application to functor input lookup
* Look up vvp_nets in the symbol table. The "source" is the label for
* the net that I want to feed, and net->port[port] is the vvp_net
* input that I want that node to feed into. When the name is found,
* put net->port[port] into the fan-out list for that node.
*/
struct functor_resolv_list_s: public resolv_list_s {
struct vvp_net_resolv_list_s: public resolv_list_s {
// node to locate
char*source;
unsigned idx;
vvp_ipoint_t port;
// port to be driven by the located node.
vvp_net_ptr_t port;
virtual bool resolve(bool mes);
};
bool functor_resolv_list_s::resolve(bool mes)
bool vvp_net_resolv_list_s::resolve(bool mes)
{
vvp_ipoint_t tmp = ipoint_lookup(source, idx);
vvp_net_t*tmp = vvp_net_lookup(source);
if (tmp) {
functor_t fport = functor_index(tmp);
functor_t iobj = functor_index(port);
iobj->port[ipoint_port(port)] = fport->out;
fport->out = port;
// Link the input port to the located output.
vvp_net_t*net = port.ptr();
net->port[port.port()] = tmp->out;
tmp->out = port;
free(source);
return true;
}
if (mes)
fprintf(stderr, "unresolved functor reference: %s\n", source);
fprintf(stderr, "unresolved vvp_net reference: %s\n", source);
return false;
}
inline static
void postpone_functor_input(vvp_ipoint_t ptr, char*lab, unsigned idx)
void postpone_functor_input(vvp_net_ptr_t port, char*lab)
{
struct functor_resolv_list_s*res = new struct functor_resolv_list_s;
struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s;
res->port = ptr;
res->port = port;
res->source = lab;
res->idx = idx;
resolv_submit(res);
}
/*
* Generic functor reference lookup.
*/
struct functor_gen_resolv_list_s: public resolv_list_s {
char*source;
unsigned idx;
vvp_ipoint_t *ref;
vvp_net_t**ref;
virtual bool resolve(bool mes);
};
bool functor_gen_resolv_list_s::resolve(bool mes)
{
vvp_ipoint_t tmp = ipoint_lookup(source, idx);
vvp_net_t*tmp = vvp_net_lookup(source);
if (tmp) {
*ref = tmp;
@ -370,14 +368,13 @@ bool functor_gen_resolv_list_s::resolve(bool mes)
return false;
}
void functor_ref_lookup(vvp_ipoint_t *ref, char*lab, unsigned idx)
void functor_ref_lookup(vvp_net_t**ref, char*lab)
{
struct functor_gen_resolv_list_s*res =
new struct functor_gen_resolv_list_s;
res->ref = ref;
res->source = lab;
res->idx = idx;
resolv_submit(res);
}
@ -653,7 +650,7 @@ void compile_vpi_time_precision(long pre)
}
/*
* Run through the arguments looking for the functors that are
* Run through the arguments looking for the nodes that are
* connected to my input ports. For each source functor that I
* find, connect the output of that functor to the indexed
* input by inserting myself (complete with the port number in
@ -666,53 +663,61 @@ void compile_vpi_time_precision(long pre)
* and skip the symbol lookup.
*/
void inputs_connect(vvp_ipoint_t fdx, unsigned argc, struct symb_s*argv)
void input_connect(vvp_net_t*fdx, unsigned port, char*label)
{
vvp_net_ptr_t ifdx = vvp_net_ptr_t(fdx, port);
char*tp;
/* Is this a vvp_vector4_t constant value? */
if ((strncmp(label, "C4<", 3) == 0)
&& ((tp = strchr(label,'>')))
&& (tp[1] == 0)
&& (strspn(label+3, "01xz") == (tp-label-3))) {
size_t v4size = tp-label-3;
vvp_vector4_t tmp (v4size);
for (unsigned idx = 0 ; idx < v4size ; idx += 1) {
vvp_bit4_t bit;
switch (label[3+idx]) {
case '0':
bit = BIT4_0;
break;
case '1':
bit = BIT4_1;
break;
case 'x':
bit = BIT4_X;
break;
case 'z':
bit = BIT4_Z;
break;
default:
assert(0);
break;
}
tmp.set_bit(v4size-idx-1, bit);
}
vvp_send_vec4(ifdx, tmp);
free(label);
return;
}
/* Handle the general case that this is a label for a node in
the vvp net. This arranges for the label to be preserved in
a linker list, and linked when the symbol table is
complete. */
postpone_functor_input(ifdx, label);
}
void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv)
{
assert(argc <= 4);
for (unsigned idx = 0; idx < argc; idx += 1) {
/* Find the functor for this input. This assumes that
wide (more then 4 inputs) gates are consecutive
functors. */
vvp_ipoint_t ifdx = ipoint_input_index(fdx, idx);
functor_t iobj = functor_index(ifdx);
if (strcmp(argv[idx].text, "C<0>") == 0)
iobj->set(ifdx, false, 0, St0);
else if (strcmp(argv[idx].text, "C<we0>") == 0)
iobj->set(ifdx, false, 0, We0);
else if (strcmp(argv[idx].text, "C<pu0>") == 0)
iobj->set(ifdx, false, 0, Pu0);
else if (strcmp(argv[idx].text, "C<su0>") == 0)
iobj->set(ifdx, false, 0, Su0);
else if (strcmp(argv[idx].text, "C<1>") == 0)
iobj->set(ifdx, false, 1, St1);
else if (strcmp(argv[idx].text, "C<we1>") == 0)
iobj->set(ifdx, false, 1, We1);
else if (strcmp(argv[idx].text, "C<pu1>") == 0)
iobj->set(ifdx, false, 1, Pu1);
else if (strcmp(argv[idx].text, "C<su1>") == 0)
iobj->set(ifdx, false, 1, Su1);
else if (strcmp(argv[idx].text, "C<x>") == 0)
iobj->set(ifdx, false, 2, StX);
else if (strcmp(argv[idx].text, "C<z>") == 0)
iobj->set(ifdx, false, 3, HiZ);
else {
postpone_functor_input(ifdx, argv[idx].text, argv[idx].idx);
continue;
}
free(argv[idx].text);
input_connect(fdx, idx, argv[idx].text);
}
}
@ -731,7 +736,7 @@ void const_functor_s::set(vvp_ipoint_t p, bool, unsigned val, unsigned)
assert(0);
}
#if 0
static vvp_ipoint_t make_const_functor(unsigned val,
unsigned str0,
unsigned str1)
@ -744,9 +749,11 @@ static vvp_ipoint_t make_const_functor(unsigned val,
return fdx;
}
#endif
/* Lookup a functor[idx] and save the ipoint in *ref. */
#if 0
static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
{
if (lab == 0)
@ -786,10 +793,11 @@ static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
functor_ref_lookup(ref, lab, idx);
return;
}
free(lab);
}
#endif
#if 0
static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
{
for (unsigned i=1; i < wid; i++) {
@ -799,33 +807,20 @@ static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
fu->base_ = fdx;
}
}
#endif
static void make_arith(vvp_arith_ *arith,
char*label, long wid,
unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t fdx = functor_allocate(wid);
functor_define(fdx, arith);
vvp_net_t* ptr = new vvp_net_t;
ptr->fun = arith;
define_functor_symbol(label, fdx);
define_functor_symbol(label, ptr);
free(label);
make_extra_outputs(fdx, wid);
unsigned opcount = argc / wid;
struct symb_s tmp_argv[4];
for (int idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(fdx,idx);
functor_t obj = functor_index(ptr);
obj->ival = 0xaa >> 2*(4 - opcount);
for (unsigned cdx = 0 ; cdx < opcount ; cdx += 1)
tmp_argv[cdx] = argv[idx + wid*cdx];
inputs_connect(ptr, opcount, tmp_argv);
}
assert(argc == 2);
inputs_connect(ptr, argc, argv);
free(argv);
}
@ -904,21 +899,13 @@ void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
if ((argc % wid) != 0) {
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label);
compile_errors += 1;
return;
}
unsigned opcount = argc / wid;
if (opcount > 4) {
fprintf(stderr, "%s; .arith has too many operands.\n", label);
if (argc != 2) {
fprintf(stderr, "%s .arith has wrong number of symbols\n", label);
compile_errors += 1;
return;
}
vvp_arith_ *arith = new vvp_arith_sum(wid);
make_arith(arith, label, wid, argc, argv);
}
@ -988,6 +975,7 @@ static void make_shift(vvp_arith_*arith,
char*label, long wid,
unsigned argc, struct symb_s*argv)
{
#if 0
vvp_ipoint_t fdx = functor_allocate(wid);
functor_define(fdx, arith);
@ -1015,7 +1003,9 @@ static void make_shift(vvp_arith_*arith,
inputs_connect(ptr, tmp_argc, tmp_argv);
}
#else
fprintf(stderr, "XXXX make_shift not implemented\n");
#endif
free(argv);
}
@ -1069,23 +1059,22 @@ void compile_shiftr(char*label, long wid, unsigned argc, struct symb_s*argv)
void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
{
assert(argc <= 4);
functor_t obj = 0;
vvp_net_fun_t* obj = 0;
if (strcmp(type,"tri") == 0) {
obj = new resolv_functor_s(HiZ);
obj = new resolv_functor(vvp_scaler_t(BIT4_Z, 0));
} else if (strcmp(type,"tri0") == 0) {
obj = new resolv_functor_s(Pu0);
obj = new resolv_functor(vvp_scaler_t(BIT4_0, 5));
} else if (strcmp(type,"tri1") == 0) {
obj = new resolv_functor_s(Pu1);
obj = new resolv_functor(vvp_scaler_t(BIT4_1, 5));
} else if (strcmp(type,"triand") == 0) {
obj = new table_functor_s(ft_TRIAND, 6, 6);
obj = new table_functor_s(ft_TRIAND);
} else if (strcmp(type,"trior") == 0) {
obj = new table_functor_s(ft_TRIOR, 6, 6);
obj = new table_functor_s(ft_TRIOR);
} else {
fprintf(stderr, "invalid resolver type: %s\n", type);
@ -1093,13 +1082,10 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
}
if (obj) {
vvp_ipoint_t fdx = functor_allocate(1);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
inputs_connect(fdx, argc, argv);
vvp_net_t*net = new vvp_net_t;
define_functor_symbol(label, net);
inputs_connect(net, argc, argv);
}
free(type);
free(label);
free(argv);
@ -1108,6 +1094,7 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
void compile_force(char*label, struct symb_s signal,
unsigned argc, struct symb_s*argv)
{
#if 0
vvp_ipoint_t ifofu = functor_allocate(argc);
define_functor_symbol(label, ifofu);
@ -1121,7 +1108,9 @@ void compile_force(char*label, struct symb_s signal,
// connect the force expression, one bit.
inputs_connect(iobj, 1, &argv[i]);
}
#else
fprintf(stderr, "XXXX compile_force not implemented\n");
#endif
free(argv);
free(signal.text);
free(label);
@ -1161,7 +1150,7 @@ void compile_udp_functor(char*label, char*type,
{
struct vvp_udp_s *u = udp_find(type);
assert (argc == u->nin);
#if 0
functor_t udp = new udp_functor_s(u);
unsigned nfun = (argc+3)/4;
@ -1186,6 +1175,9 @@ void compile_udp_functor(char*label, char*type,
if (u->sequ)
udp->put_oval(u->init, false);
#else
fprintf(stderr, "XXXX compile_udp_functor not implemented\n");
#endif
}
@ -1207,6 +1199,7 @@ void compile_memory_port(char *label, char *memid,
unsigned naddr,
unsigned argc, struct symb_s *argv)
{
#if 0
vvp_memory_t mem = memory_find(memid);
free(memid);
assert(mem);
@ -1226,6 +1219,9 @@ void compile_memory_port(char *label, char *memid,
inputs_connect(ix, argc, argv);
free(argv);
#else
fprintf(stderr, "XXXX compile_memory_port not implemented.\n");
#endif
}
void compile_memory_init(char *memid, unsigned i, unsigned char val)
@ -1322,9 +1318,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
functor_ref_lookup(&code->iptr,
opa->argv[idx].symb.text,
opa->argv[idx].symb.idx);
functor_ref_lookup(&code->net, opa->argv[idx].symb.text);
break;
case OA_FUNC_PTR2:
@ -1336,27 +1330,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
if (strcmp(opa->argv[idx].symb.text, "C<0>") == 0) {
code->iptr2 = ipoint_make(0, 0);
free(opa->argv[idx].symb.text);
} else if (strcmp(opa->argv[idx].symb.text, "C<1>") == 0) {
code->iptr2 = ipoint_make(0, 1);
free(opa->argv[idx].symb.text);
} else if (strcmp(opa->argv[idx].symb.text, "C<x>") == 0) {
code->iptr2 = ipoint_make(0, 2);
free(opa->argv[idx].symb.text);
} else if (strcmp(opa->argv[idx].symb.text, "C<z>") == 0) {
code->iptr2 = ipoint_make(0, 3);
free(opa->argv[idx].symb.text);
} else {
functor_ref_lookup(&code->iptr2,
opa->argv[idx].symb.text,
opa->argv[idx].symb.idx);
}
functor_ref_lookup(&code->net2, opa->argv[idx].symb.text);
break;
case OA_NUMBER:
@ -1519,20 +1493,15 @@ void compile_variable(char*label, char*name, int msb, int lsb,
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
functor_t fu = new var_functor_s [wid];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
functor_define(ipoint_index(fdx, idx), fu+idx);
}
count_functors_var += wid;
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
vvp_net_t*node = new vvp_net_t;
node->fun = vsig;
define_functor_symbol(label, node);
/* Make the vpiHandle for the reg. */
vvp_fvector_t vec = vvp_fvector_continuous_new(wid, fdx);
vpiHandle obj = (signed_flag > 1) ?
vpip_make_int(name, msb, lsb, vec) :
vpip_make_reg(name, msb, lsb, signed_flag!=0, vec);
vpip_make_int(name, msb, lsb, node) :
vpip_make_reg(name, msb, lsb, signed_flag!=0, node);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
@ -1540,23 +1509,35 @@ void compile_variable(char*label, char*name, int msb, int lsb,
free(name);
}
/*
* Here we handle .net records from the vvp source:
*
* <label> .net <name>, <msb>, <lsb>, <input> ;
* <label> .net/s <name>, <msb>, <lsb>, <input> ;
*
* Create a VPI handle to represent it, and fill that handle in with
* references into the net.
*/
void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
unsigned argc, struct symb_s*argv)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
vvp_fvector_t vec = vvp_fvector_new(wid);
//define_fvector_symbol(label, vec);
vvp_net_t*node = new vvp_net_t;
assert(argc == wid);
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
node->fun = vsig;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t *ref = vvp_fvector_member(vec, idx);
functor_reference(ref, argv[idx].text, argv[idx].idx);
}
/* Add the label into the functor symbol table. */
define_functor_symbol(label, node);
assert(argc == 1);
/* Connect the source to my input. */
inputs_connect(node, 1, argv);
/* Make the vpiHandle for the reg. */
vpiHandle obj = vpip_make_net(name, msb, lsb, signed_flag, vec);
vpiHandle obj = vpip_make_net(name, msb, lsb, signed_flag, node);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
@ -1579,52 +1560,10 @@ void compile_param_string(char*label, char*name, char*str, char*value)
/*
* $Log: compile.cc,v $
* Revision 1.175 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
* Revision 1.176 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.174 2004/06/30 02:15:57 steve
* Add signed LPM divide.
*
* Revision 1.173 2004/06/19 15:52:53 steve
* Add signed modulus operator.
*
* Revision 1.172 2004/06/16 16:33:26 steve
* Add structural equality compare nodes.
*
* Revision 1.171 2004/05/19 03:26:24 steve
* Support delayed/non-blocking assignment to reals and others.
*
* Revision 1.170 2003/09/04 20:26:31 steve
* Add $push flag for threads.
*
* Revision 1.169 2003/07/30 01:13:28 steve
* Add support for triand and trior.
*
* Revision 1.168 2003/07/22 20:30:24 steve
* Forgot to read the /x parameter for %load/x
*
* Revision 1.167 2003/07/03 20:03:36 steve
* Remove the vvp_cpoint_t indirect code pointer.
*
* Revision 1.166 2003/06/18 03:55:19 steve
* Add arithmetic shift operators.
*
* Revision 1.165 2003/06/17 19:17:42 steve
* Remove short int restrictions from vvp opcodes.
*
* Revision 1.164 2003/05/26 04:44:54 steve
* Add the set/x0/x instruction.
*
* Revision 1.163 2003/05/25 03:04:55 steve
* Useless cast.
*
* Revision 1.162 2003/05/24 02:48:37 steve
* More thorough overflow error message.
*
* Revision 1.161 2003/05/23 03:44:34 steve
* Assert that parameters fix into opcode.
*
* Revision 1.160 2003/04/23 03:09:25 steve
* VPI Access to named events.
*/

View File

@ -19,12 +19,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.h,v 1.56 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: compile.h,v 1.57 2004/12/11 02:31:29 steve Exp $"
#endif
# include <stdio.h>
# include "parse_misc.h"
# include "vpi_user.h"
# include "vvp_net.h"
/*
* The functions described here are the compile time support
@ -45,13 +46,13 @@ extern bool verbose_flag;
* Connect a list of symbols to a contiguous set of ipoints.
* Constants C<?> are handled by setting the ival of the ipoint.
*/
extern void inputs_connect(vvp_ipoint_t fdx, unsigned argc, struct symb_s*argv);
extern void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv);
extern void input_connect(vvp_net_t*fdx, unsigned port, char*label);
/*
* Add a functor to the symbol table
*/
extern void define_functor_symbol(const char*label, vvp_ipoint_t ipt);
extern void define_functor_symbol(const char*label, vvp_net_t*ipt);
/*
* This is a count of errors encountered during compilation. If this
@ -87,6 +88,9 @@ extern void compile_functor(char*label, char*type,
extern void compile_resolver(char*label, char*type,
unsigned argc, struct symb_s*argv);
extern void compile_part_select(char*label, char*src,
unsigned base, unsigned wid);
/*
* This is called by the parser to make force functors.
*/
@ -268,6 +272,11 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.57 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.56 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: event.cc,v 1.14 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: event.cc,v 1.15 2004/12/11 02:31:29 steve Exp $"
#endif
# include "event.h"
@ -33,87 +33,56 @@
# include <malloc.h>
#endif
event_functor_s::event_functor_s(edge_t e)
: edge(e)
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
{
return 1 << ((from << 2) | to);
}
const vvp_fun_edge::edge_t vvp_edge_posedge
= VVP_EDGE(BIT4_0,BIT4_1)
| VVP_EDGE(BIT4_0,BIT4_X)
| VVP_EDGE(BIT4_0,BIT4_Z)
| VVP_EDGE(BIT4_X,BIT4_1)
| VVP_EDGE(BIT4_Z,BIT4_1)
;
const vvp_fun_edge::edge_t vvp_edge_negedge
= VVP_EDGE(BIT4_1,BIT4_0)
| VVP_EDGE(BIT4_1,BIT4_X)
| VVP_EDGE(BIT4_1,BIT4_Z)
| VVP_EDGE(BIT4_X,BIT4_0)
| VVP_EDGE(BIT4_Z,BIT4_0)
;
const vvp_fun_edge::edge_t vvp_edge_anyedge = 0x7bde;
const vvp_fun_edge::edge_t vvp_edge_none = 0;
vvp_fun_edge::vvp_fun_edge(edge_t e)
: edge_(e)
{
threads = 0;
}
event_functor_s::~event_functor_s()
{}
/*
* Receive a value into an event functor, whether an edge or event/or.
* Detect edges, if any, then schedule awakened threads.
*/
void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
{
old_ival = ival;
put(ptr, val);
/* Only go through the effort if there is someone interested
in the results... */
if (threads || out) {
bool edge_p = true;
/* If there is an edge detect lookup table, then use the
old input and new input to detect whether this is the
requested edge. If there is no edge table, then any
set is a match. */
if (edge) {
unsigned pp = ipoint_port(ptr);
unsigned oval = (old_ival >> 2*pp) & 3;
unsigned nval = (ival >> 2*pp) & 3;
edge_p = edge & VVP_EDGE(oval,nval);
}
/* If we detect an edge, then schedule any threads that
are attached to this event, then propagate the
positive detect to the output.
Note that only other events (notably event/or
functors) can be connected to event outputs. */
if (edge_p) {
vthread_t tmp = threads;
threads = 0;
vthread_schedule_list(tmp);
if (out) {
functor_set(out, 0, St0, true);
}
// only one output? Why not propagate?
//schedule_assign(out, 0, 0);
}
}
}
named_event_functor_s::named_event_functor_s()
{
threads = 0;
}
named_event_functor_s::~named_event_functor_s()
vvp_fun_edge::~vvp_fun_edge()
{
}
void named_event_functor_s::set(vvp_ipoint_t ptr, bool push,
unsigned val, unsigned str)
void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
{
put(ptr, val);
// XXXX for now, only support first port.
assert(port.port() == 0);
if (threads) {
/* See what kind of edge this represents. */
edge_t mask = VVP_EDGE(bits_.value(0), bit.value(0));
/* Save the current input for the next time around. */
bits_ = bit;
if (threads && (edge_ & mask)) {
vthread_t tmp = threads;
threads = 0;
vthread_schedule_list(tmp);
}
vpip_run_named_event_callbacks(handle);
/* This event may nest, so progagate if I have an output. */
if (out) functor_set(out, 0, St0, true);
}
/*
@ -127,9 +96,9 @@ void named_event_functor_s::set(vvp_ipoint_t ptr, bool push,
void compile_event(char*label, char*type,
unsigned argc, struct symb_s*argv)
{
event_functor_s::edge_t edge = vvp_edge_none;
vvp_fun_edge::edge_t edge = vvp_edge_none;
if (argc && type) {
if (type) {
if (strcmp(type,"posedge") == 0)
edge = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0)
@ -137,37 +106,19 @@ void compile_event(char*label, char*type,
else if (strcmp(type,"edge") == 0)
edge = vvp_edge_anyedge;
assert(argc <= 4 || edge == vvp_edge_none);
assert(argc <= 4);
free(type);
}
free(type);
vvp_fun_edge*fun = new vvp_fun_edge(edge);
functor_t obj = new event_functor_s(edge);
vvp_net_t* ptr = new vvp_net_t;
ptr->fun = fun;
vvp_ipoint_t fdx = functor_allocate(1);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
define_functor_symbol(label, ptr);
free(label);
/* Run through the arguments looking for the functors that are
connected to my input ports. For each source functor that I
find, connect the output of that functor to the indexed
input by inserting myself (complete with the port number in
the vvp_ipoint_t) into the list that the source heads.
If the source functor is not declared yet, then don't do
the link yet. Save the reference to be resolved later. */
if (edge != vvp_edge_none)
inputs_connect(fdx, argc, argv);
else
// Are we sure that we have those .event/or
// drivers exclusively?
for (unsigned i=0; i<argc; i++) {
inputs_connect(fdx, 1, argv+i);
}
free(argv);
inputs_connect(ptr, argc, argv);
}
/*
@ -177,17 +128,12 @@ void compile_event(char*label, char*type,
*/
void compile_named_event(char*label, char*name)
{
named_event_functor_s* fp = new named_event_functor_s;
fprintf(stderr, "XXXX compile_named_event not implemented\n");
vvp_ipoint_t fdx = functor_allocate(1);
functor_define(fdx, fp);
vvp_net_t*fdx = 0;
vpiHandle obj = vpip_make_named_event(name, fdx);
/* The event needs a back pointer so that triggers to the
event functor (%set) can access the callbacks. */
fp->handle = obj;
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
@ -197,52 +143,9 @@ void compile_named_event(char*label, char*name)
/*
* $Log: event.cc,v $
* Revision 1.14 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*
* Revision 1.13 2003/11/26 01:47:18 steve
* Propagate named event outputs, if any.
*
* Revision 1.12 2003/04/23 03:09:25 steve
* VPI Access to named events.
*
* Revision 1.11 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.10 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.9 2002/07/17 18:30:01 steve
* Fix uninitialized thread pointer in named event.
*
* Revision 1.8 2002/07/05 17:14:15 steve
* Names of vpi objects allocated as vpip_strings.
*
* Revision 1.7 2002/05/19 05:18:16 steve
* Add callbacks for vpiNamedEvent objects.
*
* Revision 1.6 2002/05/18 02:34:11 steve
* Add vpi support for named events.
*
* Add vpi_mode_flag to track the mode of the
* vpi engine. This is for error checking.
*
* Revision 1.5 2002/03/17 03:24:34 steve
* Clean up edge detection code.
*
* Revision 1.4 2002/01/24 04:17:46 steve
* Spelling in comment.
*
* Revision 1.3 2001/12/29 23:59:06 steve
* push events through event/or lists.
*
* Revision 1.2 2001/11/16 04:22:27 steve
* include stdlib.h for portability.
*
* Revision 1.1 2001/11/06 03:07:22 steve
* Code rearrange. (Stephan Boettcher)
* Revision 1.15 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/

View File

@ -19,44 +19,50 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: event.h,v 1.5 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: event.h,v 1.6 2004/12/11 02:31:29 steve Exp $"
#endif
# include "functor.h"
# include "vvp_net.h"
# include "pointers.h"
/*
* Event / edge detection functors
*/
struct event_functor_s: public edge_inputs_functor_s, public waitable_hooks_s {
typedef unsigned short edge_t;
explicit event_functor_s(edge_t e);
virtual ~event_functor_s();
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
edge_t edge;
/*
* A "waitable" functor is one that the %wait instruction can wait
* on. This includes the infrastructure needed to hold threads.
*/
struct waitable_hooks_s {
vthread_t threads;
};
#define VVP_EDGE(a,b) (1<<(((a)<<2)|(b)))
/*
* The vvp_fun_edge functor detects events that are edges of various
* types. This should be hooked to a vvp_net_t that is connected to
* the output of a signal that we wish to watch for edges.
*/
class vvp_fun_edge : public vvp_net_fun_t, public waitable_hooks_s {
const event_functor_s::edge_t vvp_edge_posedge
= VVP_EDGE(0,1)
| VVP_EDGE(0,2)
| VVP_EDGE(0,3)
| VVP_EDGE(2,1)
| VVP_EDGE(3,1)
;
public:
typedef unsigned short edge_t;
explicit vvp_fun_edge(edge_t e);
const event_functor_s::edge_t vvp_edge_negedge
= VVP_EDGE(1,0)
| VVP_EDGE(1,2)
| VVP_EDGE(1,3)
| VVP_EDGE(2,0)
| VVP_EDGE(3,0)
;
virtual ~vvp_fun_edge();
const event_functor_s::edge_t vvp_edge_anyedge = 0x7bde;
const event_functor_s::edge_t vvp_edge_none = 0;
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
private:
vvp_vector4_t bits_;
edge_t edge_;
};
extern const vvp_fun_edge::edge_t vvp_edge_posedge;
extern const vvp_fun_edge::edge_t vvp_edge_negedge;
extern const vvp_fun_edge::edge_t vvp_edge_anyedge;
extern const vvp_fun_edge::edge_t vvp_edge_none;
#if 0
/*
* This is a functor to represent named events. This functor has no
* inputs, and no output. It is a functor so that the %wait and %set
@ -77,9 +83,15 @@ struct named_event_functor_s : public waitable_hooks_s, public functor_s {
*/
struct callback_functor_s *vvp_fvector_make_callback
(vvp_fvector_t, event_functor_s::edge_t = vvp_edge_none);
#endif
/*
* $Log: event.h,v $
* Revision 1.6 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.5 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*

View File

@ -0,0 +1,41 @@
:vpi_module "system";
;
; This example demonstrates a simple blocking assignment to a
; reg vector within a module.
;
main .scope module, "main" "main";
; This declares a "reg" data type named "test" in the current scope.
; The bit range is given for the purposes of VPI access. The range
; corresponds to the declaration "reg [7:0] test", so leads to an 8
; bit wide vector.
test .var "test", 7, 0;
; The %assign/v0 opcode assigns a vector to the .var at the label,
; with the given delay. The width of the vector from index register0.
T0 %ix/load 0, 8 ; Set the width of the vector to 8.
%assign/v0 test, 2, 0 ;
%delay 3;
%vpi_call "$display", "test = %b", test;
%assign/v0 test, 2, 1 ;
%delay 1;
%vpi_call "$display", "test = %b", test;
%delay 2;
%vpi_call "$display", "test = %b", test;
%assign/v0 test, 2, 2 ;
%delay 3;
%vpi_call "$display", "test = %b", test;
%assign/v0 test, 2, 3 ;
%delay 3;
%vpi_call "$display", "test = %b", test;
%end;
.thread T0;

35
vvp/examples/set_reg.vvp Normal file
View File

@ -0,0 +1,35 @@
:vpi_module "system";
;
; This example demonstrates a simple blocking assignment to a
; reg vector within a module.
;
main .scope module, "main" "main";
; This declares a "reg" data type named "test" in the current scope.
; The bit range is given for the purposes of VPI access. The range
; corresponds to the declaration "reg [7:0] test", so leads to an 8
; bit wide vector.
test .var "test", 7, 0;
; The %set/v opcode writes a value to the target .var vector. The
; first operand is the label of the .var object. The second and
; third operands are the base and width of the bit set that is to
; be made into the vector to write.
T0 %set/v test, 0, 8 ;
%vpi_call "$display", "test = %b", test;
%set/v test, 1, 8 ;
%vpi_call "$display", "test = %b", test;
%set/v test, 2, 8 ;
%vpi_call "$display", "test = %b", test;
%set/v test, 3, 8 ;
%vpi_call "$display", "test = %b", test;
%end;
.thread T0;

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: force.cc,v 1.8 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: force.cc,v 1.9 2004/12/11 02:31:29 steve Exp $"
#endif
# include "codes.h"
@ -104,6 +104,7 @@ static bool release_force(vvp_ipoint_t itgt, functor_t tgt)
*/
bool of_FORCE(vthread_t thr, vvp_code_t cp)
{
#if 0
unsigned wid = cp->bit_idx[0];
for (unsigned i=0; i<wid; i++) {
@ -141,7 +142,9 @@ bool of_FORCE(vthread_t thr, vvp_code_t cp)
// on its forced value.
fofu->set(ifofu, false, fofu->get_oval(), fofu->get_ostr());
}
#else
fprintf(stderr, "XXXX forgot how to implement %%force\n");
#endif
return true;
}
@ -151,12 +154,15 @@ bool of_FORCE(vthread_t thr, vvp_code_t cp)
*/
bool of_RELEASE(vthread_t thr, vvp_code_t cp)
{
#if 0
vvp_ipoint_t itgt = cp->iptr;
functor_t tgt = functor_index(itgt);
if (release_force(itgt, tgt))
tgt->enable(itgt);
#else
fprintf(stderr, "XXXX forgot how to implement %%release\n");
#endif
return true;
}
@ -213,84 +219,14 @@ bool var_functor_s::deassign(vvp_ipoint_t itgt)
return false;
}
/*
* The %cassign instruction causes a variable functor (the target) the
* receive a behavioral continuous assignment from the functor on the
* right (the source expression). If the source functor address is 0,
* then the port part is a constant value to write into the target.
*/
bool of_CASSIGN(vthread_t thr, vvp_code_t cp)
{
vvp_ipoint_t itgt = cp->iptr;
vvp_ipoint_t iexp = cp->iptr2;
functor_t tgt = functor_index(itgt);
var_functor_s *var = dynamic_cast<var_functor_s *>(tgt);
assert(var);
var->deassign(itgt);
// a constant expression?
if (ipoint_make(iexp, 0) == 0) {
tgt->port[3] = ipoint_make(0, 3);
tgt->set(ipoint_make(itgt, 1), true, ipoint_port(iexp));
return true;
}
functor_t fu = functor_index(iexp);
tgt->port[3] = iexp;
tgt->port[1] = fu->out;
fu->out = ipoint_make(itgt, 1);
tgt->set(ipoint_make(itgt, 1), true, fu->get());
return true;
}
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
{
vvp_ipoint_t itgt = cp->iptr;
unsigned wid = cp->bit_idx[0];
for (unsigned i = 0; i<wid; i++) {
vvp_ipoint_t ipt = ipoint_index(itgt, i);
functor_t tgt = functor_index(ipt);
var_functor_s *var = dynamic_cast<var_functor_s *>(tgt);
assert(var);
var->deassign(ipt);
}
return true;
}
/*
* $Log: force.cc,v $
* Revision 1.9 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.8 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*
* Revision 1.7 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2002/08/07 00:54:20 steve
* Documentation, and excessive inlines.
*
* Revision 1.5 2002/03/17 03:23:11 steve
* Force the push flags to be explicit.
*
* Revision 1.4 2001/12/06 03:31:24 steve
* Support functor delays for gates and UDP devices.
* (Stephan Boettcher)
*
* Revision 1.3 2001/11/07 03:34:42 steve
* Use functor pointers where vvp_ipoint_t is unneeded.
*
* Revision 1.2 2001/11/01 04:42:40 steve
* Handle procedural constant functor pointers.
*
* Revision 1.1 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
*/

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.h,v 1.52 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: functor.h,v 1.53 2004/12/11 02:31:29 steve Exp $"
#endif
# include "pointers.h"
@ -277,15 +277,6 @@ unsigned functor_get(vvp_ipoint_t ptr)
// Special infrastructure functor types
/*
* A "waitable" functor is one that the %wait instruction can wait
* on. This includes the infrastructure needed to hold threads.
*/
struct waitable_hooks_s {
vthread_t threads;
};
// The extra_outputs_functor_s class is for devices that require
// multiple inputs and outputs.
// ->set redirects the job to the base_, who knows what shall be done.
@ -343,6 +334,11 @@ extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
/*
* $Log: functor.h,v $
* Revision 1.53 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.52 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.43 2004/06/30 02:15:57 steve Exp $"
#ident "$Id: lexor.lex,v 1.44 2004/12/11 02:31:29 steve Exp $"
#endif
# include "parse_misc.h"
@ -101,6 +101,7 @@
".net" { return K_NET; }
".net/s" { return K_NET_S; }
".param" { return K_PARAM; }
".part" { return K_PART; }
".resolv" { return K_RESOLV; }
".scope" { return K_SCOPE; }
".shift/l" { return K_SHIFTL; }
@ -182,6 +183,11 @@ int yywrap()
/*
* $Log: lexor.lex,v $
* Revision 1.44 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.43 2004/06/30 02:15:57 steve
* Add signed LPM divide.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -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.13 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: logic.cc,v 1.14 2004/12/11 02:31:29 steve Exp $"
#endif
# include "logic.h"
@ -38,36 +38,14 @@
* to 4 inputs.
*/
table_functor_s::table_functor_s(truth_t t, unsigned str0, unsigned str1)
table_functor_s::table_functor_s(truth_t t)
: table(t)
{
count_functors_table += 1;
assert(str0 <= 7);
assert(str1 <= 7);
odrive0 = str0;
odrive1 = str1;
}
table_functor_s::~table_functor_s()
{}
void table_functor_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned)
{
/* Load the new value into the standard ival vector. */
put(ptr, v);
/* Locate the new output value in the table. */
unsigned char val = table[ival >> 2];
val >>= 2 * (ival&0x03);
val &= 0x03;
/* Send the output. Do *not* push the value, because logic
devices in Verilog are supposed to suppress 0-time
pulses. If we were to push the value, The gate on this
device's output would receive every change that happened,
thus allowing full transport propagation, instead of the
proper ballistic propagation. */
put_oval(val, false);
}
/*
@ -80,26 +58,26 @@ void compile_functor(char*label, char*type,
vvp_delay_t delay, unsigned ostr0, unsigned ostr1,
unsigned argc, struct symb_s*argv)
{
functor_t obj;
table_functor_s* obj = 0;
if (strcmp(type, "OR") == 0) {
obj = new table_functor_s(ft_OR, ostr0, ostr1);
obj = new table_functor_s(ft_OR);
} else if (strcmp(type, "AND") == 0) {
obj = new table_functor_s(ft_AND, ostr0, ostr1);
obj = new table_functor_s(ft_AND);
} else if (strcmp(type, "BUF") == 0) {
obj = new table_functor_s(ft_BUF, ostr0, ostr1);
obj = new table_functor_s(ft_BUF);
#if 0
} else if (strcmp(type, "BUFIF0") == 0) {
obj = new vvp_bufif_s(true,false, ostr0, ostr1);
} else if (strcmp(type, "BUFIF1") == 0) {
obj = new vvp_bufif_s(false,false, ostr0, ostr1);
#endif
} else if (strcmp(type, "BUFZ") == 0) {
obj = new table_functor_s(ft_BUFZ, ostr0, ostr1);
obj = new table_functor_s(ft_BUFZ);
#if 0
} else if (strcmp(type, "PMOS") == 0) {
obj = new vvp_pmos_s;
@ -111,7 +89,7 @@ void compile_functor(char*label, char*type,
} else if (strcmp(type, "RNMOS") == 0) {
obj = new vvp_rnmos_s;
#endif
} else if (strcmp(type, "MUXX") == 0) {
obj = new table_functor_s(ft_MUXX);
@ -122,25 +100,25 @@ void compile_functor(char*label, char*type,
obj = new table_functor_s(ft_EEQ);
} else if (strcmp(type, "NAND") == 0) {
obj = new table_functor_s(ft_NAND, ostr0, ostr1);
obj = new table_functor_s(ft_NAND);
} else if (strcmp(type, "NOR") == 0) {
obj = new table_functor_s(ft_NOR, ostr0, ostr1);
obj = new table_functor_s(ft_NOR);
} else if (strcmp(type, "NOT") == 0) {
obj = new table_functor_s(ft_NOT, ostr0, ostr1);
obj = new table_functor_s(ft_NOT);
#if 0
} else if (strcmp(type, "NOTIF0") == 0) {
obj = new vvp_bufif_s(true,true, ostr0, ostr1);
} else if (strcmp(type, "NOTIF1") == 0) {
obj = new vvp_bufif_s(false,true, ostr0, ostr1);
#endif
} else if (strcmp(type, "XNOR") == 0) {
obj = new table_functor_s(ft_XNOR, ostr0, ostr1);
obj = new table_functor_s(ft_XNOR);
} else if (strcmp(type, "XOR") == 0) {
obj = new table_functor_s(ft_XOR, ostr0, ostr1);
obj = new table_functor_s(ft_XOR);
} else {
yyerror("invalid functor type.");
@ -153,61 +131,22 @@ void compile_functor(char*label, char*type,
free(type);
assert(argc <= 4);
vvp_ipoint_t fdx = functor_allocate(1);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
vvp_net_t*net = new vvp_net_t;
define_functor_symbol(label, net);
free(label);
obj->delay = delay;
inputs_connect(fdx, argc, argv);
inputs_connect(net, argc, argv);
free(argv);
}
/*
* $Log: logic.cc,v $
* Revision 1.13 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*
* 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.
*
* Revision 1.9 2002/07/05 20:08:44 steve
* Count different types of functors.
*
* Revision 1.8 2002/03/17 05:48:49 steve
* Do not push values through logic gates.
*
* Revision 1.7 2002/01/12 04:02:16 steve
* Support the BUFZ logic device.
*
* Revision 1.6 2001/12/14 06:03:17 steve
* Arrange bufif to support notif as well.
*
* Revision 1.5 2001/12/14 02:04:49 steve
* Support strength syntax on functors.
*
* Revision 1.4 2001/12/06 03:31:24 steve
* Support functor delays for gates and UDP devices.
* (Stephan Boettcher)
*
* Revision 1.3 2001/11/16 04:22:27 steve
* include stdlib.h for portability.
*
* Revision 1.2 2001/11/07 03:34:42 steve
* Use functor pointers where vvp_ipoint_t is unneeded.
*
* Revision 1.1 2001/11/06 03:07:22 steve
* Code rearrange. (Stephan Boettcher)
* Revision 1.14 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/

View File

@ -1,7 +1,7 @@
#ifndef __logic_H
#define __logic_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,25 +19,25 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: logic.h,v 1.7 2003/07/30 01:13:29 steve Exp $"
#ident "$Id: logic.h,v 1.8 2004/12/11 02:31:29 steve Exp $"
#endif
# include "functor.h"
# include "vvp_net.h"
# include <stddef.h>
/*
* Table driven functor. oval = table[ival];
* Table driven functor. This kind of node takes 4 inputs and
* generates a single output. The logic is bitwise, and implemented
* with a lookup table.
*/
class table_functor_s: public functor_s {
class table_functor_s: public vvp_net_fun_t {
public:
typedef const unsigned char *truth_t;
explicit table_functor_s(truth_t t, unsigned str0 =6, unsigned str1 =6);
explicit table_functor_s(truth_t t);
virtual ~table_functor_s();
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
private:
truth_t table;
};
@ -66,26 +66,10 @@ extern const unsigned char ft_var[];
/*
* $Log: logic.h,v $
* Revision 1.7 2003/07/30 01:13:29 steve
* Add support for triand and trior.
*
* 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.
*
* Revision 1.4 2002/07/05 20:08:44 steve
* Count different types of functors.
*
* Revision 1.3 2002/01/12 04:02:16 steve
* Support the BUFZ logic device.
*
* Revision 1.2 2001/12/14 02:04:49 steve
* Support strength syntax on functors.
*
* Revision 1.1 2001/11/06 03:07:22 steve
* Code rearrange. (Stephan Boettcher)
* Revision 1.8 2004/12/11 02:31:29 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/
#endif // __logic_H

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.55 2004/06/19 15:52:53 steve Exp $
* $Id: opcodes.txt,v 1.56 2004/12/11 02:31:29 steve Exp $
*/
@ -57,9 +57,8 @@ means the following:
1 and 1 --> 1
otherwise x
* %assign <var-label>, <delay>, <bit>
* %assign/d <var-label>, <delay>, <bit>
* %assign/v0 <var-label>, <delay>, <bit>
* %assign <var-label>, <delay>, <bit> (DEPRECATED -- use %assign/v0)
* %assign/d <var-label>, <delay>, <bit> (DEPRECATED -- need %assign/v0/d)
This does a non-blocking assignment to a variable. The <label>
identifies the affected variable, and the <delay> gives the delay when
@ -71,9 +70,6 @@ The %assign/d instruction is exactly the same as the %assign
instruction, except that the <delay> specifies one of the index
registers, that contain a calculated delay.
The %assign/v0 instruction is a vector version of %assign, with the
vector width in index register 0.
* %assign/m <memory-label>, <delay>, <bit>
This instruction does a non-blocking assignment to a bit in a memory
@ -81,6 +77,16 @@ from the specified thread register <bit>. The memory bit is addressed
by index register 3. Bit address zero is the LSB of the first memory
word.
* %assign/v0 <var-label>, <delay>, <bit>
The %assign/v0 instruction is a vector version of non-blocking
assignment. The <delay> is the number of clock ticks in the future
where the assignment should be schedule, and the <bit> is the base of
the vector to be assigned to the destination. The vector width is in
index register 0.
The <var-label> references a .var object that can receive non-blocking
assignments. For blocking assignments, see %set/v.
* %assign/wr <vpi-label>, <delay>, <index>
@ -124,20 +130,17 @@ debugger commands.
This may not work on all platforms. If run-time debugging is compiled
out, then this function is a no-op.
* %cassign/v <var-label>, <bit>, <wid>
* %cassign <var-label>, <expr-label>
Perform a continuous assign of a constant value to the target
variable. This is similar to %set, but it uses the cassign port
(port-1) of the signal functor instead of the normal assign, so the
signal responds differently.
Connect and active a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable, and the
<expr-label> is the functor that drives the expression to the
variable. This opcode affects only a single bit.
* %deassign <var-label>, <wid>
* %deassign <var-label>
Deactivate and disconnect a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable. <wid>
specifies the how many bits to deassign.
variable. The <var-label> identifies the affected variable.
* %cmp/u <bit-l>, <bit-r>, <wid>
@ -294,7 +297,7 @@ bits.
This instruction loads an immediate value into the addressed index
register. The index register holds numeric values, so the <value> is a
number. The idx value selects the index register, and may be 0, 1, 2
or 3. This is different from %is/get, which loads the index register
or 3. This is different from %ix/get, which loads the index register
from a value in the thread bit vector.
@ -338,19 +341,6 @@ If the matching child instruction is still running, a %join suspends
the calling thread until the child ends. If the child is already
ended, then the %join does not block or yield the thread.
* %load <bit>, <functor-label>
* %load/v <bit>, <functor-label>, <wid>
This instruction loads a value from the given functor output into the
specified thread register bit. The functor-label can refer to a .net,
a .var or a .functor, and may be indexed with array syntax to get at a
functor within a vector of functors. This instruction loads only a
single bit.
The %load/v instruction is a vector version, that loads an entire
vector, starting at the given <bit> and functor.
* %load/m <bit>, <memory-label>
This instruction loads a value from a memory bit into the specified
@ -365,6 +355,15 @@ This instruction load a value from a .net object bit. Since .net
objects don't really exist (they are only named indirection into the
netlist) this instruction indexes into the .net list of bits.
* %load/v <bit>, <functor-label>, <wid>
This instruction loads a vector value from the given functor node into
the specified thread register bit. The functor-label can refer to a
.net, a .var or a .functor with a vector output. The entire vector,
from the least significant up to <wid> bits, is loaded starting at
thread bit <bit>. It is an error for the width to not match the vector
width at the functor.
* %load/wr <bit>, <vpi-label>
This instruction reads a real value from the vpi-like object to a word
@ -497,7 +496,6 @@ semantics. Like:
%release <functor-label> ; remove the force
* %set <var-label>, <bit>
* %set/v <var-label>, <bit>, <wid>
This sets a bit of a variable, and is used to implement blocking

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.60 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: parse.y,v 1.61 2004/12/11 02:31:30 steve Exp $"
#endif
# include "parse_misc.h"
@ -60,7 +60,7 @@ extern FILE*yyin;
%token K_ARITH_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
%token K_ARITH_SUB K_ARITH_SUM
%token K_CMP_EQ K_CMP_NE K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM K_PART
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
%token K_UDP K_UDP_C K_UDP_S
%token K_MEM K_MEM_P K_MEM_I
@ -181,6 +181,12 @@ statement
compile_resolver($1, $3, obj.cnt, obj.vect);
}
/* Part select statements take a single netlist input, and numbers
that define the part to be selected out of the input. */
| T_LABEL K_PART T_SYMBOL ',' T_NUMBER ',' T_NUMBER ';'
{ compile_part_select($1, $3, $5, $7); }
/* Force statements are very much like functors. They are
compiled to functors of a different mode. */
@ -566,10 +572,6 @@ symbol
{ $$.text = $1;
$$.idx = 0;
}
| T_SYMBOL '[' T_NUMBER ']'
{ $$.text = $1;
$$.idx = $3;
}
;
symbol_opt
@ -635,6 +637,11 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.61 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.60 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*

75
vvp/part.cc Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: part.cc,v 1.1 2004/12/11 02:31:30 steve Exp $"
# include "compile.h"
# include "vvp_net.h"
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <assert.h>
vvp_fun_part::vvp_fun_part(unsigned base, unsigned wid)
: base_(base), wid_(wid)
{
}
vvp_fun_part::~vvp_fun_part()
{
}
void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
{
assert(port.port() == 0);
vvp_vector4_t res(wid_);
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
if (idx + base_ < bit.size())
res.set_bit(idx, bit.value(base_+idx));
else
res.set_bit(idx, BIT4_X);
}
}
void compile_part_select(char*label, char*source,
unsigned base, unsigned wid)
{
vvp_fun_part*fun = new vvp_fun_part(base, wid);
vvp_net_t*net = new vvp_net_t;
net->fun = fun;
define_functor_symbol(label, net);
free(label);
input_connect(net, 0, source);
}
/*
* $Log: part.cc,v $
* Revision 1.1 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -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.17 2003/03/13 04:36:57 steve Exp $"
#ident "$Id: resolv.cc,v 1.18 2004/12/11 02:31:30 steve Exp $"
#endif
# include "resolv.h"
@ -25,6 +25,7 @@
# include "statistics.h"
# include <assert.h>
#if 0
/*
* A signal value is unambiguous if the top 4 bits and the bottom 4
* bits are identical. This means that the VSSSvsss bits of the 8bit
@ -187,31 +188,30 @@ void resolv_functor_s::set(vvp_ipoint_t i, bool push, unsigned, unsigned str)
put_ostr(val, sval, false);
}
#else
resolv_functor::resolv_functor(vvp_scaler_t hiz_value)
: hiz_(hiz_value)
{
}
resolv_functor::~resolv_functor()
{
}
void resolv_functor::recv_vec8(vvp_vector8_t vit)
{
assert(0); // XXXX not implemented yet!
}
#endif
/*
* $Log: resolv.cc,v $
* Revision 1.17 2003/03/13 04:36:57 steve
* Remove the obsolete functor delete functions.
* Revision 1.18 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.16 2003/02/09 23:33:26 steve
* Spelling fixes.
*
* 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.
*
* Revision 1.13 2002/07/05 20:08:44 steve
* Count different types of functors.
*
* Revision 1.12 2001/12/18 05:32:11 steve
* Improved functor debug dumps.
*
* Revision 1.11 2001/12/15 02:11:51 steve
* Give tri0 and tri1 their proper strengths.
*/

View File

@ -19,59 +19,41 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: resolv.h,v 1.8 2003/03/13 04:36:57 steve Exp $"
#ident "$Id: resolv.h,v 1.9 2004/12/11 02:31:30 steve Exp $"
#endif
# include "config.h"
# include "functor.h"
# include "vvp_net.h"
/*
* This functor type resolves its inputs using the verilog method of
* combining signals, and outputs that resolved value. The puller
* value is also blended with the result. This helps with the
* implementation of tri0 and tri1, which have pull constants attached.
* implementation of tri0 and tri1, which have pull constants
* attached.
*
* This node takes in vvp_vector8_t values, and emits a vvp_vector8_t
* value.
*/
class resolv_functor_s: public functor_s {
class resolv_functor : public vvp_net_fun_t {
public:
explicit resolv_functor_s(unsigned char hiz_value);
~resolv_functor_s();
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
explicit resolv_functor(vvp_scaler_t hiz_value);
~resolv_functor();
void recv_vec8(vvp_vector8_t bit);
private:
unsigned char istr[4];
unsigned char hiz_;
vvp_vector8_t driven_;
vvp_scaler_t hiz_;
};
/*
* $Log: resolv.h,v $
* Revision 1.8 2003/03/13 04:36:57 steve
* Remove the obsolete functor delete functions.
*
* Revision 1.7 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/12/18 05:32:11 steve
* Improved functor debug dumps.
*
* Revision 1.5 2001/12/15 02:11:51 steve
* Give tri0 and tri1 their proper strengths.
*
* Revision 1.4 2001/12/15 01:54:39 steve
* Support tri0 and tri1 resolvers.
*
* Revision 1.3 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.2 2001/05/12 01:48:57 steve
* Silly copyright typo.
*
* Revision 1.1 2001/05/09 02:53:53 steve
* Implement the .resolv syntax.
* Revision 1.9 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/
#endif

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: schedule.cc,v 1.28 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: schedule.cc,v 1.29 2004/12/11 02:31:30 steve Exp $"
#endif
# include "schedule.h"
@ -43,30 +43,19 @@ unsigned long count_time_pool = 0;
/*
* The event_s and event_time_s structures implement the Verilog
* stratified event queue. The event_time_s objects are one per time
* step. Each time step in turn contains a list of event_s objects
* that are the actual events.
* stratified event queue.
*
* The event_time_s objects are one per time step. Each time step in
* turn contains a list of event_s objects that are the actual events.
*
* The event_s objects are base classes for the more specific sort of
* event.
*/
struct event_s {
union {
vthread_t thr;
vvp_ipoint_t fun;
functor_t funp;
vvp_gen_event_t obj;
};
unsigned val :2;
unsigned type :2;
struct event_s*next;
void* operator new (size_t);
void operator delete(void*obj, size_t s);
virtual ~event_s() { }
virtual void run_run(void) =0;
};
const unsigned TYPE_GEN = 0;
const unsigned TYPE_THREAD = 1;
const unsigned TYPE_PROP = 2;
const unsigned TYPE_ASSIGN = 3;
struct event_time_s {
vvp_time64_t delay;
@ -81,43 +70,50 @@ struct event_time_s {
void operator delete(void*obj, size_t s);
};
/*
* Derived event types
*/
struct vthread_event_s : public event_s {
vthread_t thr;
void run_run(void);
};
void vthread_event_s::run_run(void)
{
count_thread_events += 1;
vthread_run(thr);
}
struct assign_vector4_event_s : public event_s {
vvp_net_ptr_t ptr;
vvp_vector4_t val;
void run_run(void);
};
void assign_vector4_event_s::run_run(void)
{
count_assign_events += 1;
vvp_send_vec4(ptr, val);
}
struct generic_event_s : public event_s {
vvp_gen_event_t obj;
unsigned char val;
void run_run(void);
};
void generic_event_s::run_run(void)
{
count_gen_events += 1;
if (obj && obj->run)
obj->run(obj, val);
}
/*
** These event_s will be required a lot, at high frequency.
** These event_time_s will be required a lot, at high frequency.
** Once allocated, we never free them, but stash them away for next time.
*/
static struct event_s* event_free_list = 0;
static const unsigned CHUNK_COUNT = 8192 / sizeof(struct event_s);
inline void* event_s::operator new (size_t size)
{
assert(size == sizeof(struct event_s));
struct event_s* cur = event_free_list;
if (!cur) {
cur = (struct event_s*)
malloc(CHUNK_COUNT * sizeof(struct event_s));
for (unsigned idx = 1 ; idx < CHUNK_COUNT ; idx += 1) {
cur[idx].next = event_free_list;
event_free_list = cur + idx;
}
count_event_pool += CHUNK_COUNT;
} else {
event_free_list = cur->next;
}
return cur;
}
inline void event_s::operator delete(void*obj, size_t size)
{
struct event_s*cur = reinterpret_cast<event_s*>(obj);
cur->next = event_free_list;
event_free_list = cur;
}
static struct event_time_s* time_free_list = 0;
static const unsigned TIME_CHUNK_COUNT = 8192 / sizeof(struct event_time_s);
@ -374,10 +370,9 @@ static struct event_s* pull_sync_event(void)
void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
{
struct event_s*cur = new event_s;
struct vthread_event_s*cur = new vthread_event_s;
cur->thr = thr;
cur->type = TYPE_THREAD;
vthread_mark_scheduled(thr);
if (push_flag && (delay == 0)) {
@ -394,14 +389,19 @@ void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
void functor_s::schedule(vvp_time64_t delay, bool nba_flag)
{
#if 0
struct event_s*cur = new event_s;
cur->funp = this;
cur->type = TYPE_PROP;
schedule_event_(cur, delay, nba_flag? SEQ_NBASSIGN:SEQ_ACTIVE);
#else
fprintf(stderr, "XXXX I forgot how to schedule functors.\n");
#endif
}
#if 0
void schedule_assign(vvp_ipoint_t fun, unsigned char val, vvp_time64_t delay)
{
struct event_s*cur = new event_s;
@ -412,15 +412,25 @@ void schedule_assign(vvp_ipoint_t fun, unsigned char val, vvp_time64_t delay)
schedule_event_(cur, delay, SEQ_NBASSIGN);
}
#endif
void schedule_assign_vector(vvp_net_ptr_t ptr,
vvp_vector4_t bit,
vvp_time64_t delay)
{
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
cur->ptr = ptr;
cur->val = bit;
schedule_event_(cur, delay, SEQ_NBASSIGN);
}
void schedule_generic(vvp_gen_event_t obj, unsigned char val,
vvp_time64_t delay, bool sync_flag)
{
struct event_s*cur = new event_s;
struct generic_event_s*cur = new generic_event_s;
cur->obj = obj;
cur->val = val;
cur->type= TYPE_GEN;
schedule_event_(cur, delay, sync_flag? SEQ_ROSYNC : SEQ_ACTIVE);
}
@ -459,10 +469,7 @@ void schedule_simulate(void)
struct event_s*sync_cur;
while ( (sync_cur = pull_sync_event()) ) {
assert(sync_cur->type == TYPE_GEN);
if (sync_cur->obj && sync_cur->obj->run) {
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
}
sync_cur->run_run();
delete sync_cur;
}
@ -499,6 +506,8 @@ void schedule_simulate(void)
ctim->active->next = cur->next;
}
cur->run_run();
#if 0
switch (cur->type) {
case TYPE_THREAD:
count_thread_events += 1;
@ -529,7 +538,7 @@ void schedule_simulate(void)
break;
}
#endif
delete (cur);
}
@ -539,10 +548,7 @@ void schedule_simulate(void)
for (struct event_s*sync_cur = pull_sync_event()
; sync_cur ; sync_cur = pull_sync_event()) {
assert(sync_cur->type == TYPE_GEN);
if (sync_cur->obj && sync_cur->obj->run)
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
sync_cur->run_run();
delete (sync_cur);
}
@ -556,6 +562,11 @@ void schedule_simulate(void)
/*
* $Log: schedule.cc,v $
* Revision 1.29 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.28 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*
@ -570,8 +581,5 @@ void schedule_simulate(void)
*
* Revision 1.24 2003/02/22 02:52:06 steve
* Check for stopped flag in certain strategic points.
*
* Revision 1.23 2003/02/21 03:40:35 steve
* Add vpiStop and interactive mode.
*/

View File

@ -19,11 +19,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: schedule.h,v 1.16 2003/09/09 00:56:45 steve Exp $"
#ident "$Id: schedule.h,v 1.17 2004/12/11 02:31:30 steve Exp $"
#endif
# include "vthread.h"
# include "pointers.h"
# include "vvp_net.h"
/*
* This causes a thread to be scheduled for execution. The schedule
@ -41,8 +42,9 @@ extern void schedule_vthread(vthread_t thr, vvp_time64_t delay,
* Create an assignment event. The val passed here will be assigned to
* the specified input when the delay times out.
*/
extern void schedule_assign(vvp_ipoint_t fun, unsigned char val,
vvp_time64_t delay);
extern void schedule_assign_vector(vvp_net_ptr_t ptr,
vvp_vector4_t val,
vvp_time64_t delay);
/*
@ -108,28 +110,15 @@ extern unsigned long count_event_pool;
/*
* $Log: schedule.h,v $
* Revision 1.17 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.16 2003/09/09 00:56:45 steve
* Reimpelement scheduler to divide nonblocking assign queue out.
*
* Revision 1.15 2003/02/22 02:52:06 steve
* Check for stopped flag in certain strategic points.
*
* Revision 1.14 2003/02/21 03:40:35 steve
* Add vpiStop and interactive mode.
*
* Revision 1.13 2003/02/09 23:33:26 steve
* Spelling fixes.
*
* Revision 1.12 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.11 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.10 2002/05/12 23:44:41 steve
* task calls and forks push the thread event in the queue.
*/
#endif

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: symbols.h,v 1.4 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: symbols.h,v 1.5 2004/12/11 02:31:30 steve Exp $"
#endif
/*
@ -39,6 +39,7 @@
*/
# include "config.h"
# include "vvp_net.h"
/*
* This is the basic type of a symbol table. It is opaque. Don't even
@ -49,8 +50,9 @@ typedef struct symbol_table_s *symbol_table_t;
typedef struct symbol_value_s {
union {
unsigned long num;
vvp_net_t*net;
void*ptr;
unsigned long num;
};
} symbol_value_t;
@ -79,6 +81,11 @@ symbol_value_t sym_get_value(symbol_table_t tbl, const char*key);
/*
* $Log: symbols.h,v $
* Revision 1.5 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.4 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ufunc.cc,v 1.4 2003/07/03 20:03:36 steve Exp $"
#ident "$Id: ufunc.cc,v 1.5 2004/12/11 02:31:30 steve Exp $"
#endif
# include "compile.h"
@ -138,7 +138,7 @@ void compile_ufunc(char*label, char*code, unsigned wid,
unsigned portc, struct symb_s*portv,
unsigned retc, struct symb_s*retv)
{
#if 0
/* Create an array of vvp_ipoint_t pointers, that point to the
.var bits of the function ports. Do this for the input
ports and the output port. */
@ -232,10 +232,18 @@ void compile_ufunc(char*label, char*code, unsigned wid,
}
inputs_connect(ibase, argc, argv);
#else
fprintf(stderr, "XXXX compile_ufunc not implemented.\n");
#endif
}
/*
* $Log: ufunc.cc,v $
* Revision 1.5 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.4 2003/07/03 20:03:36 steve
* Remove the vvp_cpoint_t indirect code pointer.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_callback.cc,v 1.34 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: vpi_callback.cc,v 1.35 2004/12/11 02:31:30 steve Exp $"
#endif
/*
@ -96,85 +96,6 @@ struct __vpiCallback* new_vpi_callback()
return obj;
}
/*
* The callback_functor_s functor is used to support cbValueChange
* callbacks. When a value change callback is created, instances of
* this functor are created to receive values and detect changes in
* the functor web at the right spot.
*/
struct callback_functor_s: public functor_s {
callback_functor_s();
virtual ~callback_functor_s();
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
struct __vpiCallback *cb_handle;
};
callback_functor_s::callback_functor_s()
{}
callback_functor_s::~callback_functor_s()
{}
/*
* Make the functors necessary to support an edge callback. This is a
* single event functor that is in turn fed by edge detector functors
* attached to all the input bit functors. (Just like an event-or.)
* This function creates the callback_functor and the necessary event
* functors, and attaches the event functors to the net.
*/
struct callback_functor_s *vvp_fvector_make_callback(vvp_fvector_t vec,
event_functor_s::edge_t edge)
{
// Let's make a callback functor.
struct callback_functor_s *obj = new callback_functor_s;
// We want to connect nvec inputs
unsigned nvec = vvp_fvector_size(vec);
// We require a total of nfun functors. If there's an edge to
// look for, then all inputs must go to extra event functors.
// Otherwise we just make sure we have one input left on the base
// functor to connect the extras to, if there are any.
unsigned nfun = (nvec+3)/4;
if (edge != vvp_edge_none)
nfun ++ ;
else if (nfun > 1 && 4*nfun == nvec)
nfun ++;
vvp_ipoint_t fdx = functor_allocate(nfun);
functor_define(fdx, obj);
for (unsigned i=1; i<nfun; i++) {
functor_t fu = new event_functor_s(edge);
functor_define(ipoint_index(fdx, i), fu);
fu->out = fdx;
}
unsigned i;
if (edge != vvp_edge_none)
i = 4;
else if (nvec > 4)
i = 1;
else
i = 0;
for (unsigned vi = 0; vi < nvec; vi++, i++) {
vvp_ipoint_t vipt = vvp_fvector_get(vec, vi);
functor_t vfu = functor_index(vipt);
vvp_ipoint_t ipt = ipoint_input_index(fdx, i);
functor_t fu = functor_index(ipt);
unsigned pp = ipoint_port(ipt);
fu->port[pp] = vfu->out;
vfu->out = ipt;
}
obj->cb_handle = 0;
return obj;
}
/*
* A value change callback is tripped when a bit of a signal
@ -202,21 +123,18 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
case vpiReg:
case vpiNet:
case vpiIntegerVar:
/* Attach the callback to the vvp_fun_signal node by
putting it in the vpi_callbacks list. */
struct __vpiSignal*sig;
sig = reinterpret_cast<__vpiSignal*>(data->obj);
/* Create callback functors, if necessary, to do the
value change detection and carry the callback
objects. */
if (sig->callback == 0) {
sig->callback = vvp_fvector_make_callback(sig->bits);
assert(sig->callback);
}
vvp_fun_signal*sig_fun;
sig_fun = dynamic_cast<vvp_fun_signal*>(sig->node->fun);
assert(sig_fun);
/* Attach the __vpiCallback object to the signals
callback functors. */
obj->next = sig->callback->cb_handle;
sig->callback->cb_handle = obj;
/* Attach the __vpiCallback object to the signal. */
obj->next = sig_fun->vpi_callbacks;
sig_fun->vpi_callbacks = obj;
break;
case vpiRealVar:
@ -512,25 +430,25 @@ void callback_execute(struct __vpiCallback*cur)
}
/*
* A callback_functor_s functor uses its set method to detect value
* changes. When a value comes in, the __vpiCallback objects that are
* associated with this callback functor are all called.
* A vvp_fun_signal uses this method to run its callbacks whenever it
* has a value change. If the cb_rtn is non-nil, then call the
* callback function. If the cb_rtn pointer is nil, then the object
* has been marked for deletion. Free it.
*/
void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
void vvp_fun_signal::run_vpi_callbacks()
{
struct __vpiCallback *next = cb_handle;
struct __vpiCallback *next = vpi_callbacks;
struct __vpiCallback *prev = 0;
while (next) {
struct __vpiCallback * cur = next;
struct __vpiCallback*cur = next;
next = cur->next;
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;
cur->cb_data.value->value.scalar = value(0);
break;
case vpiSuppressVal:
break;
@ -546,7 +464,7 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
} else if (prev == 0) {
cb_handle = next;
vpi_callbacks = next;
cur->next = 0;
vpi_free_object(&cur->base);
@ -556,89 +474,21 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
cur->next = 0;
vpi_free_object(&cur->base);
}
}
}
/*
* $Log: vpi_callback.cc,v $
* Revision 1.35 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.34 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*
* Revision 1.33 2004/02/18 02:51:59 steve
* Fix type mismatches of various VPI functions.
*
* Revision 1.32 2003/09/09 00:56:45 steve
* Reimpelement scheduler to divide nonblocking assign queue out.
*
* Revision 1.31 2003/04/25 04:36:42 steve
* Properly skip cancelled callbacks.
*
* Revision 1.30 2003/04/19 23:32:57 steve
* Add support for cbNextSimTime.
*
* Revision 1.29 2003/03/12 02:50:32 steve
* Add VPI tracing.
*
* Revision 1.28 2003/02/17 00:58:38 steve
* Strict correctness of vpi_free_object results.
*
* Revision 1.27 2003/02/10 05:20:10 steve
* Add value change callbacks to real variables.
*
* Revision 1.26 2003/02/09 23:33:26 steve
* Spelling fixes.
*
* 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.
*
* Revision 1.22 2002/07/31 03:22:23 steve
* Set vpi_mode_flag to represent cpReadOnlySync actions.
*
* Revision 1.21 2002/07/12 02:07:36 steve
* vpiIntegerVars can have callbacks.
*
* Revision 1.20 2002/06/11 03:47:34 steve
* Stub value change callbacks for consts and modules.
*
* Revision 1.19 2002/06/02 19:05:50 steve
* Check for null pointers from users.
*
* Revision 1.18 2002/05/28 22:55:20 steve
* Callbacks can happen during calltf functions.
*
* Revision 1.17 2002/05/19 05:18:16 steve
* Add callbacks for vpiNamedEvent objects.
*
* Revision 1.16 2002/05/18 02:34:11 steve
* Add vpi support for named events.
*
* Add vpi_mode_flag to track the mode of the
* vpi engine. This is for error checking.
*
* Revision 1.15 2002/05/09 03:34:31 steve
* Handle null time and calltf pointers.
*
* Revision 1.14 2002/05/04 03:17:29 steve
* Properly free vpi callback objects.
*
* Revision 1.13 2002/05/04 03:03:17 steve
* Add simulator event callbacks.
*
* Revision 1.12 2002/04/20 04:33:23 steve
* Support specified times in cbReadOnlySync, and
* add support for cbReadWriteSync.
* Keep simulation time in a 64bit number.
*
* Revision 1.11 2002/04/06 20:25:45 steve
* cbValueChange automatically replays.
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_event.cc,v 1.9 2003/05/04 20:43:36 steve Exp $"
#ident "$Id: vpi_event.cc,v 1.10 2004/12/11 02:31:30 steve Exp $"
#endif
# include "vpi_priv.h"
@ -86,7 +86,7 @@ static const struct __vpirt vpip_named_event_rt = {
0
};
vpiHandle vpip_make_named_event(const char*name, vvp_ipoint_t funct)
vpiHandle vpip_make_named_event(const char*name, vvp_net_t*funct)
{
struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)
malloc(sizeof(struct __vpiNamedEvent));
@ -142,6 +142,11 @@ void vpip_run_named_event_callbacks(vpiHandle ref)
/*
* $Log: vpi_event.cc,v $
* Revision 1.10 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.9 2003/05/04 20:43:36 steve
* Event callbacks support vpi_remove_cb.
*

View File

@ -19,11 +19,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.h,v 1.59 2004/10/04 01:10:59 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.60 2004/12/11 02:31:30 steve Exp $"
#endif
# include "vpi_user.h"
# include "pointers.h"
# include "vvp_net.h"
# include "memory.h"
/*
@ -177,16 +178,14 @@ struct __vpiSignal {
unsigned signed_flag : 1;
unsigned isint_ : 1; // original type was integer
/* The represented value is here. */
vvp_fvector_t bits;
/* This is the callback event functor */
struct callback_functor_s *callback;
vvp_net_t*node;
};
extern vpiHandle vpip_make_int(const char*name, int msb, int lsb,
vvp_fvector_t vec);
vvp_net_t*vec);
extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
bool signed_flag, vvp_fvector_t vec);
bool signed_flag, vvp_net_t*net);
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
bool signed_flag, vvp_fvector_t vec);
bool signed_flag, vvp_net_t*node);
/*
* These methods support the vpi creation of events. The name string
@ -200,12 +199,12 @@ struct __vpiNamedEvent {
/* Parent scope of this object. */
struct __vpiScope*scope;
/* The functor, used for %set operations. */
vvp_ipoint_t funct;
vvp_net_t*funct;
/* List of callbacks interested in this event. */
struct __vpiCallback*callbacks;
};
extern vpiHandle vpip_make_named_event(const char*name, vvp_ipoint_t f);
extern vpiHandle vpip_make_named_event(const char*name, vvp_net_t*f);
extern void vpip_run_named_event_callbacks(vpiHandle ref);
extern void vpip_real_value_change(struct __vpiCallback*cbh,
vpiHandle ref);
@ -418,6 +417,11 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
/*
* $Log: vpi_priv.h,v $
* Revision 1.60 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.59 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_signal.cc,v 1.62 2004/05/19 03:26:25 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.63 2004/12/11 02:31:30 steve Exp $"
#endif
/*
@ -107,7 +107,7 @@ static int signal_get(int code, vpiHandle ref)
case _vpiNexusId:
if (rfp->msb == rfp->lsb)
return vvp_fvector_get(rfp->bits, 0);
return (int)rfp->node;
else
return 0;
@ -178,10 +178,12 @@ static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1);
unsigned char*bits = new unsigned char[wid];
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
/* FIXME: bits should be an array of vvp_bit4_t. */
unsigned char* bits = new unsigned char[wid];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
bits[idx] = functor_get(fptr);
bits[idx] = vsig->value(idx);
}
unsigned hwid = (wid+2) / 3 + 1;
@ -201,6 +203,7 @@ static char *signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1);
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
/* The result will use a character for each 8 bits of the
vector. Add one extra character for the highest bits that
@ -211,13 +214,12 @@ static char *signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
char tmp = 0;
int bitnr;
for(bitnr=wid-1; bitnr>=0; bitnr--){
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, bitnr);
tmp <<= 1;
switch (functor_get(fptr)) {
case 0:
switch (vsig->value(bitnr)) {
case BIT4_0:
break;
case 1:
case BIT4_1:
tmp |= 1;
break;
default:
@ -254,6 +256,9 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
unsigned wid = (rfp->msb >= rfp->lsb)
? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1);
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
char *rbuf = 0;
switch (vp->format) {
@ -262,11 +267,10 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
assert(wid <= 8 * sizeof vp->value.integer);
vp->value.integer = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
switch (functor_get(fptr)) {
case 0:
switch (vsig->value(idx)) {
case BIT4_0:
break;
case 1:
case BIT4_1:
vp->value.integer |= 1<<idx;
break;
default:
@ -278,18 +282,17 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
break;
case vpiScalarVal: {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, 0);
switch (functor_get(fptr)) {
case 0:
switch (vsig->value(0)) {
case BIT4_0:
vp->value.scalar = vpi0;
break;
case 1:
case BIT4_1:
vp->value.scalar = vpi1;
break;
case 2:
case BIT4_X:
vp->value.scalar = vpiX;
break;
case 3:
case BIT4_Z:
vp->value.scalar = vpiZ;
break;
}
@ -301,8 +304,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf = need_result_buf(wid+1, RBUF_VAL);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
rbuf[wid-idx-1] = "01xz"[functor_get(fptr)];
rbuf[wid-idx-1] = "01xz"[vsig->value(idx)];
}
rbuf[wid] = 0;
vp->value.str = rbuf;
@ -316,8 +318,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf[hwid] = 0;
hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
hval = hval | (functor_get(fptr) << 2*(idx % 4));
hval = hval | (vsig->value(idx) << 2*(idx % 4));
if (idx%4 == 3) {
hwid -= 1;
@ -353,8 +354,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf[hwid] = 0;
hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
hval = hval | (functor_get(fptr) << 2*(idx % 3));
hval = hval | (vsig->value(idx) << 2*(idx % 3));
if (idx%3 == 2) {
hwid -= 1;
@ -400,21 +400,20 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
op->aval = op->bval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
switch (functor_get(fptr)) {
case 0:
switch (vsig->value(idx)) {
case BIT4_0:
op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit);
break;
case 1:
case BIT4_1:
op->aval |= (1 << obit);
op->bval &= ~(1 << obit);
break;
case 2:
case BIT4_X:
op->aval |= (1 << obit);
op->bval |= (1 << obit);
break;
case 3:
case BIT4_Z:
op->aval &= ~(1 << obit);
op->bval |= (1 << obit);
break;
@ -430,51 +429,6 @@ 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: get_value: "
"value type %u not implemented."
@ -494,14 +448,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
unsigned val, unsigned str, unsigned long dly =0)
{
vvp_ipoint_t ptr = vvp_fvector_get(rfp->bits,idx);
if (dly > 0) {
schedule_assign(ptr, val, dly);
} else {
functor_t fu = functor_index(ptr);
fu->put_ostr(val, str, true);
}
fprintf(stderr, "XXXX functor_poke not implemented\n");
}
static void signal_put_stringval(struct __vpiSignal*rfp, unsigned wid,
@ -762,7 +709,7 @@ static const struct __vpirt vpip_net_rt = {
* to minimize the code modifications. Icarus implements integers
* as 'reg signed [31:0]'.
*/
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_fvector_t vec)
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net(name, msb,lsb, true, vec);
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
@ -775,7 +722,7 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_fvector_t vec)
* Construct a vpiReg object. It's like a net, except for the type.
*/
vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
bool signed_flag, vvp_fvector_t vec)
bool signed_flag, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
obj->vpi_type = &vpip_reg_rt;
@ -804,7 +751,7 @@ static struct __vpiSignal* allocate_vpiSignal(void)
* and point to the specified functor for the lsb.
*/
vpiHandle vpip_make_net(const char*name, int msb, int lsb,
bool signed_flag, vvp_fvector_t vec)
bool signed_flag, vvp_net_t*node)
{
struct __vpiSignal*obj = allocate_vpiSignal();
obj->base.vpi_type = &vpip_net_rt;
@ -813,8 +760,7 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
obj->lsb = lsb;
obj->signed_flag = signed_flag? 1 : 0;
obj->isint_ = false;
obj->bits = vec;
obj->callback = 0;
obj->node = node;
obj->scope = vpip_peek_current_scope();
@ -826,6 +772,11 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.63 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.62 2004/05/19 03:26:25 steve
* Support delayed/non-blocking assignment to reals and others.
*

View File

@ -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.122 2004/10/04 01:11:00 steve Exp $"
#ident "$Id: vthread.cc,v 1.123 2004/12/11 02:31:30 steve Exp $"
#endif
# include "config.h"
@ -138,12 +138,12 @@ static void thr_check_addr(struct vthread_s*thr, unsigned addr)
}
}
static inline unsigned thr_get_bit(struct vthread_s*thr, unsigned addr)
static inline vvp_bit4_t thr_get_bit(struct vthread_s*thr, unsigned addr)
{
assert(addr < thr->nbits);
unsigned idx = addr % (CPU_WORD_BITS/2);
addr /= (CPU_WORD_BITS/2);
return (thr->bits[addr] >> (idx*2)) & 3UL;
return (vvp_bit4_t) ((thr->bits[addr] >> (idx*2)) & 3UL);
}
static inline void thr_put_bit(struct vthread_s*thr,
@ -218,6 +218,31 @@ static unsigned long* vector_to_array(struct vthread_s*thr,
return 0;
}
/*
* This function gets from the thread a vector of bits starting from
* the addressed location and for the specified width.
*/
static vvp_vector4_t vthread_bits_to_vector(struct vthread_s*thr,
unsigned bit, unsigned wid)
{
/* Make a vector of the desired width. */
vvp_vector4_t value (wid);
if (bit >= 4) {
for (unsigned idx = 0; idx < wid; idx +=1, bit += 1) {
vvp_bit4_t bit_val = thr_get_bit(thr, bit);
value.set_bit(idx, bit_val);
}
} else {
vvp_bit4_t bit_val = (vvp_bit4_t)bit;
for (unsigned idx = 0; idx < wid; idx +=1, bit += 1) {
value.set_bit(idx, bit_val);
}
}
return value;
}
/*
* Create a new thread with the given start address.
@ -517,18 +542,15 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_ASSIGN(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
schedule_assign(cp->iptr, bit_val, cp->bit_idx[0]);
return true;
}
bool of_ASSIGN_D(vthread_t thr, vvp_code_t cp)
{
#if 0
assert(cp->bit_idx[0] < 4);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
schedule_assign(cp->iptr, bit_val, thr->words[cp->bit_idx[0]].w_int);
#else
fprintf(stderr, "XXXX forgot how to implemented %%assign/d\n");
#endif
return true;
}
@ -544,15 +566,10 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
unsigned delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
unsigned char bit_val = thr_get_bit(thr, bit);
schedule_assign(iptr, bit_val, delay);
if (bit >= 4)
bit += 1;
}
vvp_net_ptr_t ptr (cp->net, 0);
schedule_assign_vector(ptr, value, delay);
return true;
}
@ -584,9 +601,13 @@ bool of_ASSIGN_WR(vthread_t thr, vvp_code_t cp)
bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
#if 0
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
vvp_ipoint_t itmp = ipoint_index(cp->iptr, thr->words[0].w_int);
schedule_assign(itmp, bit_val, cp->bit_idx[0]);
#else
fprintf(stderr, "XXXX forgot how to implement %%assign/x0\n");
#endif
return true;
}
@ -624,6 +645,34 @@ bool of_BREAKPOINT(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* the %cassign/v instruction invokes a continuous assign of a
* constant value to a signal. The instruction arguments are:
*
* %cassign/v <net>, <base>, <wid> ;
*
* Where the <net> is the net label assembled into a vvp_net pointer,
* and the <base> and <wid> are stashed in the bit_idx array.
*
* This instruction writes vvp_vector4_t values to port-1 of the
* target signal.
*/
bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned base = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
/* Collect the thread bits into a vector4 item. */
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
/* set the value into port 1 of the destination. */
vvp_net_ptr_t ptr (net, 1);
vvp_send_vec4(ptr, value);
return true;
}
bool of_CMPS(vthread_t thr, vvp_code_t cp)
{
unsigned eq = 1;
@ -879,6 +928,21 @@ bool of_CVT_VR(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* This implements the %deassign instruction. All we do is write a
* long(1) to port-3 of the addressed net. This turns off an active
* continuous assign activated by %cassign/v
*/
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
vvp_net_ptr_t ptr (net, 3);
vvp_send_long(ptr, 1);
return true;
}
bool of_DELAY(vthread_t thr, vvp_code_t cp)
{
//printf("thread %p: %%delay %lu\n", thr, cp->number);
@ -1566,13 +1630,6 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
return false;
}
bool of_LOAD(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
thr_put_bit(thr, cp->bit_idx[0], functor_get(cp->iptr));
return true;
}
bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
@ -1582,7 +1639,15 @@ bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
}
/*
* Load net/indexed.
* %load/nx <bit>, <vpi-label>, <idx> ; Load net/indexed.
*
* cp->bit_idx[0] contains the <bit> value, an index into the thread
* bit register.
*
* cp->bin_idx[1] is the <idx> value from the words array.
*
* cp->handle is the linked reference to the __vpiSignal that we are
* to read from.
*/
bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
{
@ -1595,21 +1660,47 @@ bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
unsigned idx = thr->words[cp->bit_idx[1]].w_int;
vvp_ipoint_t ptr = vvp_fvector_get(sig->bits, idx);
thr_put_bit(thr, cp->bit_idx[0], functor_get(ptr));
vvp_fun_signal*fun = dynamic_cast<vvp_fun_signal*>(sig->node->fun);
assert(sig != 0);
vvp_bit4_t val = fun->value(idx);
thr_put_bit(thr, cp->bit_idx[0], val);
return true;
}
/* %load/v <bit>, <label>, <wid>
*
* Implement the %load/v instruction. Load the vector value of the
* requested width from the <label> functor starting in the thread bit
* <bit>.
*
* The <bit> value is the destination in the thread vector store, and
* is in cp->bit_idx[0].
*
* The <wid> value is the expected with of the vector, and is in
* cp->bit_idx[1].
*
* The functor to read from is the vvp_net_t object pointed to by the
* cp->net pointer.
*/
bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0];
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
unsigned wid = cp->bit_idx[1];
vvp_net_t*net = cp->net;
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
thr_put_bit(thr, bit, functor_get(iptr));
/* For the %load to work, the functor must actually be a
signal functor. Only signals save their vector value. */
vvp_fun_signal*sig = dynamic_cast<vvp_fun_signal*> (net->fun);
assert(sig);
for (unsigned idx = 0; idx < wid; idx += 1, bit += 1) {
vvp_bit4_t val = sig->value(idx);
thr_put_bit(thr, bit, val);
}
return true;
@ -1633,8 +1724,12 @@ bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
assert(cp->bit_idx[0] >= 4);
assert(cp->bit_idx[1] < 4);
#if 0
vvp_ipoint_t ptr = ipoint_index(cp->iptr, thr->words[cp->bit_idx[1]].w_int);
thr_put_bit(thr, cp->bit_idx[0], functor_get(ptr));
#else
fprintf(stderr, "XXXX forgot how to implement %%load/x\n");
#endif
return true;
}
@ -2429,14 +2524,6 @@ bool of_NOR(vthread_t thr, vvp_code_t cp)
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
bool of_SET(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
functor_set(cp->iptr, bit_val, strong_values[bit_val], true);
return true;
}
bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
{
unsigned char val = thr_get_bit(thr, cp->bit_idx[0]);
@ -2445,26 +2532,30 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* This implements the "%set/v <label>, <bit>, <wid>" instruction.
*
* The <label> is a reference to a vvp_net_t object, and it is in
* cp->net.
*
* The <bit> is the thread bit address, and is in cp->bin_idx[0].
*
* The <wid> is the width of the vector I'm to make, and is in
* cp->bin_idx[1].
*/
bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0];
if (bit >= 4) {
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
unsigned char bit_val = thr_get_bit(thr, bit);
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
functor_set(iptr, bit_val, strong_values[bit_val], true);
}
unsigned wid = cp->bit_idx[1];
} else {
unsigned char bit_val = strong_values[bit];
/* Make a vector of the desired width. */
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
/* set the value into port 0 of the destination. */
vvp_net_ptr_t ptr (cp->net, 0);
vvp_send_vec4(ptr, value);
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
functor_set(iptr, bit, bit_val, true);
}
}
return true;
}
@ -2502,12 +2593,16 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
if ((unsigned)idx > cp->bit_idx[1])
return true;
#if 0
/* Form the functor pointer from the base pointer and the
index from the index register. */
vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx);
/* Set the value. */
functor_set(itmp, bit_val, strong_values[bit_val], true);
#else
fprintf(stderr, "XXXX forgot how to implement %%set/x0\n");
#endif
return true;
}
@ -2527,12 +2622,16 @@ bool of_SET_X0_X(vthread_t thr, vvp_code_t cp)
if (idx > lim)
return true;
#if 0
/* Form the functor pointer from the base pointer and the
index from the index register. */
vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx);
/* Set the value. */
functor_set(itmp, bit_val, strong_values[bit_val], true);
#else
fprintf(stderr, "XXXX forgot how to implement %%set/x0/x\n");
#endif
return true;
}
@ -2727,19 +2826,25 @@ bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
return schedule_finished()? false : true;
}
/*
* Implement the wait by locating the functor for the event, and
* adding this thread to the threads list for the event.
/* %wait <label>;
* Implement the wait by locating the vvp_net_T for the event, and
* adding this thread to the threads list for the event. The some
* argument is the reference to the functor to wait for. This must be
* an event object of some sort.
*/
bool of_WAIT(vthread_t thr, vvp_code_t cp)
{
assert(! thr->waiting_for_event);
thr->waiting_for_event = 1;
waitable_hooks_s* ep = dynamic_cast<waitable_hooks_s*>(functor_index(cp->iptr));
vvp_net_t*net = cp->net;
/* Get the functor as a waitable_hooks_s object. */
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (net->fun);
assert(ep);
/* Add this thread to the list in the event. */
thr->wait_next = ep->threads;
ep->threads = thr;
/* Return false to suspend this thread. */
return false;
}
@ -2874,6 +2979,11 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.123 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.122 2004/10/04 01:11:00 steve
* Clean up spurious trailing white space.
*

494
vvp/vvp_net.cc Normal file
View File

@ -0,0 +1,494 @@
/*
* Copyright (c) 2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: vvp_net.cc,v 1.1 2004/12/11 02:31:30 steve Exp $"
# include "vvp_net.h"
# include <stdio.h>
# include <typeinfo>
# include <assert.h>
/* *** BIT operations *** */
vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
{
if ((a|b|c) > 1) {
c = BIT4_X;
return BIT4_X;
}
int sum = a + b + c;
switch (sum) {
case 0:
return BIT4_0;
case 1:
c = BIT4_0;
return BIT4_1;
case 2:
c = BIT4_1;
return BIT4_0;
case 3:
c = BIT4_1;
return BIT4_1;
default:
assert(0);
}
}
void vvp_send_vec4(vvp_net_ptr_t ptr, vvp_vector4_t val)
{
while (struct vvp_net_t*cur = ptr.ptr()) {
vvp_net_ptr_t next = cur->port[ptr.port()];
if (cur->fun)
cur->fun->recv_vec4(ptr, val);
ptr = next;
}
}
void vvp_send_real(vvp_net_ptr_t ptr, double val)
{
while (struct vvp_net_t*cur = ptr.ptr()) {
vvp_net_ptr_t next = cur->port[ptr.port()];
if (cur->fun)
cur->fun->recv_real(ptr, val);
ptr = next;
}
}
void vvp_send_long(vvp_net_ptr_t ptr, long val)
{
while (struct vvp_net_t*cur = ptr.ptr()) {
vvp_net_ptr_t next = cur->port[ptr.port()];
if (cur->fun)
cur->fun->recv_long(ptr, val);
ptr = next;
}
}
const unsigned bits_per_word = sizeof (unsigned long) / 2;
vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that)
{
size_ = that.size_;
if (size_ > bits_per_word) {
unsigned words = (size_+bits_per_word-1) / bits_per_word;
bits_ptr_ = new unsigned long[words];
for (unsigned idx = 0 ; idx < words ; idx += 1)
bits_ptr_[idx] = that.bits_ptr_[idx];
} else {
bits_val_ = that.bits_val_;
}
}
vvp_vector4_t::vvp_vector4_t(unsigned size)
: size_(size)
{
/* Make a work full of initialized bits. */
unsigned long initial_value_bits = 0xaa;
for (unsigned idx = 0 ; idx < sizeof (unsigned long) ; idx += 1)
initial_value_bits = (initial_value_bits << 8) | 0xaa;
if (size_ > bits_per_word) {
unsigned cnt = (size_ + bits_per_word - 1) / bits_per_word;
bits_ptr_ = new unsigned long[cnt];
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
bits_ptr_[idx] = initial_value_bits;
} else {
bits_val_ = initial_value_bits;
}
}
vvp_vector4_t::~vvp_vector4_t()
{
if (size_ > bits_per_word) {
delete[] bits_ptr_;
}
}
vvp_vector4_t& vvp_vector4_t::operator= (const vvp_vector4_t&that)
{
if (size_ > bits_per_word)
delete[] bits_ptr_;
size_ = that.size_;
if (size_ > bits_per_word) {
unsigned cnt = (size_ + bits_per_word - 1) / bits_per_word;
bits_ptr_ = new unsigned long[cnt];
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
bits_ptr_[idx] = that.bits_ptr_[idx];
} else {
bits_val_ = that.bits_val_;
}
return *this;
}
vvp_bit4_t vvp_vector4_t::value(unsigned idx) const
{
if (idx >= size_)
return BIT4_X;
unsigned wdx = idx / bits_per_word;
unsigned off = idx % bits_per_word;
unsigned long bits;
if (size_ > bits_per_word) {
bits = bits_ptr_[wdx];
} else {
bits = bits_val_;
}
bits >>= (off * 2);
/* Casting is evil, but this cast matches the un-cast done
when the vvp_bit4_t value is put into the vector. */
return (vvp_bit4_t) (bits & 3);
}
void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
{
assert(idx < size_);
unsigned wdx = idx / bits_per_word;
unsigned off = idx % bits_per_word;
unsigned long mask = 3UL << (2*off);
if (size_ > bits_per_word) {
bits_ptr_[wdx] &= ~mask;
bits_ptr_[wdx] |= val << (2*off);
} else {
bits_val_ &= ~mask;
bits_val_ |= val << (2*off);
}
}
vvp_vector8_t::vvp_vector8_t(unsigned size)
: size_(size)
{
if (size_ == 0) {
bits_ = 0;
return;
}
bits_ = new vvp_scaler_t[size_];
}
vvp_vector8_t::~vvp_vector8_t()
{
if (size_ > 0)
delete[]bits_;
}
vvp_net_fun_t::vvp_net_fun_t()
{
}
vvp_net_fun_t::~vvp_net_fun_t()
{
}
void vvp_net_fun_t::recv_vec4(vvp_net_ptr_t, vvp_vector4_t)
{
fprintf(stderr, "internal error: %s: recv_vec4 not implemented\n",
typeid(*this).name());
assert(0);
}
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t, vvp_vector8_t)
{
fprintf(stderr, "internal error: %s: recv_vec8 not implemented\n",
typeid(*this).name());
assert(0);
}
void vvp_net_fun_t::recv_real(vvp_net_ptr_t, double)
{
fprintf(stderr, "internal error: %s: recv_real not implemented\n",
typeid(*this).name());
assert(0);
}
void vvp_net_fun_t::recv_long(vvp_net_ptr_t, long)
{
fprintf(stderr, "internal error: %s: recv_long not implemented\n",
typeid(*this).name());
assert(0);
}
/* **** vvp_fun_signal methods **** */
vvp_fun_signal::vvp_fun_signal(unsigned wid)
{
vpi_callbacks = 0;
continuous_assign_active_ = false;
}
/*
* Nets simply reflect their input to their output.
*/
void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
{
switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process)
if (! continuous_assign_active_) {
bits_ = bit;
vvp_send_vec4(ptr.ptr()->out, bit);
run_vpi_callbacks();
}
break;
case 1: // Continuous assign value
continuous_assign_active_ = true;
bits_ = bit;
vvp_send_vec4(ptr.ptr()->out, bit);
run_vpi_callbacks();
break;
case 2: // Force value
assert(0);
break;
default:
assert(0);
break;
}
}
void vvp_fun_signal::deassign()
{
continuous_assign_active_ = false;
}
/*
* The signal functor takes commands as long values to port-3. This
* method interprets those commands.
*/
void vvp_fun_signal::recv_long(vvp_net_ptr_t ptr, long bit)
{
switch (ptr.port()) {
case 3: // Command port
switch (bit) {
case 1: // deassign command
deassign();
break;
default:
assert(0);
break;
}
break;
default: // Other ports ar errors.
assert(0);
break;
}
}
vvp_bit4_t vvp_fun_signal::value(unsigned idx) const
{
return bits_.value(idx);
}
/* **** vvp_scaler_t methods **** */
/*
* DRIVE STRENGTHS:
*
* The normal functor is not aware of strengths. It generates strength
* simply by virtue of having strength specifications. The drive
* strength specification includes a drive0 and drive1 strength, each
* with 8 possible values (that can be represented in 3 bits) as given
* in this table:
*
* HiZ = 0,
* SMALL = 1,
* MEDIUM = 2,
* WEAK = 3,
* LARGE = 4,
* PULL = 5,
* STRONG = 6,
* SUPPLY = 7
*
* The vvp_signal_t value, however, is a combination of value and
* strength, used in strength-aware contexts.
*
* OUTPUT STRENGTHS:
*
* The strength-aware values are specified as an 8 bit value, that is
* two 4 bit numbers. The value is encoded with two drive strengths (0-7)
* and two drive values (0 or 1). Each nibble contains three bits of
* strength and one bit of value, like so: VSSS. The high nibble has
* the strength-value closest to supply1, and the low nibble has the
* strength-value closest to supply0.
*/
/*
* A signal value is unambiguous if the top 4 bits and the bottom 4
* bits are identical. This means that the VSSSvsss bits of the 8bit
* value have V==v and SSS==sss.
*/
# define UNAMBIG(v) (((v) & 0x0f) == (((v) >> 4) & 0x0f))
# define STREN1(v) ( ((v)&0x80)? ((v)&0xf0) : (0x70 - ((v)&0xf0)) )
# define STREN0(v) ( ((v)&0x08)? ((v)&0x0f) : (0x07 - ((v)&0x0f)) )
vvp_scaler_t::vvp_scaler_t(vvp_bit4_t val, unsigned str)
{
assert(str <= 7);
switch (val) {
case BIT4_0:
value_ = str | (str<<4);
break;
case BIT4_1:
value_ = str | (str<<4) | 0x88;
break;
case BIT4_X:
value_ = str | (str<<4) | 0x80;
case BIT4_Z:
value_ = 0;
break;
}
}
vvp_scaler_t::vvp_scaler_t()
{
value_ = 0;
}
vvp_scaler_t resolve(vvp_scaler_t a, vvp_scaler_t b)
{
// If the value is 0, that is the same as HiZ. In that case,
// resolution is simply a matter of returning the *other* value.
if (a.value_ == 0)
return b;
if (b.value_ == 0)
return a;
vvp_scaler_t res = a;
if (UNAMBIG(a.value_) && UNAMBIG(b.value_)) {
/* If both signals are unambiguous, simply choose
the stronger. If they have the same strength
but different values, then this becomes
ambiguous. */
if (a.value_ == b.value_) {
/* values are equal. do nothing. */
} else if ((b.value_&0x07) > (res.value_&0x07)) {
/* New value is stronger. Take it. */
res.value_ = b.value_;
} else if ((b.value_&0x77) == (res.value_&0x77)) {
/* Strengths are the same. Make value ambiguous. */
res.value_ = (res.value_&0x70) | (b.value_&0x07) | 0x80;
} else {
/* Must be res is the stronger one. */
}
} else if (UNAMBIG(res.value_)) {
unsigned tmp = 0;
if ((res.value_&0x70) > (b.value_&0x70))
tmp |= res.value_&0xf0;
else
tmp |= b.value_&0xf0;
if ((res.value_&0x07) > (b.value_&0x07))
tmp |= res.value_&0x0f;
else
tmp |= b.value_&0x0f;
res.value_ = tmp;
} else if (UNAMBIG(b.value_)) {
/* If one of the signals is unambiguous, then it
will sweep up the weaker parts of the ambiguous
signal. The result may be ambiguous, or maybe not. */
unsigned tmp = 0;
if ((b.value_&0x70) > (res.value_&0x70))
tmp |= b.value_&0xf0;
else
tmp |= res.value_&0xf0;
if ((b.value_&0x07) > (res.value_&0x07))
tmp |= b.value_&0x0f;
else
tmp |= res.value_&0x0f;
res.value_ = tmp;
} else {
/* If both signals are ambiguous, then the result
has an even wider ambiguity. */
unsigned tmp = 0;
if (STREN1(b.value_) > STREN1(res.value_))
tmp |= b.value_&0xf0;
else
tmp |= res.value_&0xf0;
if (STREN0(b.value_) < STREN0(res.value_))
tmp |= b.value_&0x0f;
else
tmp |= res.value_&0x0f;
res.value_ = tmp;
}
/* Canonicalize the HiZ value. */
if ((res.value_&0x77) == 0)
res.value_ = 0;
return res;
}
/*
* $Log: vvp_net.cc,v $
* Revision 1.1 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/

407
vvp/vvp_net.h Normal file
View File

@ -0,0 +1,407 @@
#ifndef __vvp_net_H
#define __vvp_net_H
/*
* Copyright (c) 2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: vvp_net.h,v 1.1 2004/12/11 02:31:30 steve Exp $"
# include <assert.h>
/* Data types */
class vvp_scaler_t;
/* Basic netlist types. */
class vvp_net_t;
class vvp_net_ptr_t;
class vvp_net_fun_t;
/* Core net function types. */
class vvp_fun_concat;
class vvp_fun_drive;
class vvp_fun_part;
/*
* This is the set of Verilog 4-value bit values. Scalers have this
* value along with strength, vectors are a collection of these
* values. The enumeration has fixed numeric values that can be
* expressed in 2 real bits, so that some of the internal classes can
* pack them tightly.
*/
enum vvp_bit4_t {
BIT4_0 = 0,
BIT4_1 = 1,
BIT4_X = 2,
BIT4_Z = 3
};
extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c);
/*
* This class represents scaler values collected into vectors. The
* vector values can be accessed individually, or treated as a
* unit. in any case, the elements of the vector are addressed from
* zero(LSB) to size-1(MSB).
*
* No strength values are stored here, if strengths are needed, use a
* collection of vvp_scaler_t objects instead.
*/
class vvp_vector4_t {
public:
explicit vvp_vector4_t(unsigned size =0);
~vvp_vector4_t();
unsigned size() const { return size_; }
vvp_bit4_t value(unsigned idx) const;
void set_bit(unsigned idx, vvp_bit4_t val);
vvp_vector4_t(const vvp_vector4_t&that);
vvp_vector4_t& operator= (const vvp_vector4_t&that);
private:
unsigned size_;
union {
unsigned long bits_val_;
unsigned long*bits_ptr_;
};
};
/*
* This class represents a scaler value with strength. These are
* heavier then the simple vvp_bit4_t, but more information is
* carried by that weight.
*
* The strength values are as defined here:
* HiZ - 0
* Small - 1
* Medium - 2
* Weak - 3
* Large - 4
* Pull - 5
* Strong - 6
* Supply - 7
*/
class vvp_scaler_t {
friend vvp_scaler_t resolve(vvp_scaler_t a, vvp_scaler_t b);
public:
// Make a HiZ value.
explicit vvp_scaler_t();
// Make an unambiguous value.
explicit vvp_scaler_t(vvp_bit4_t val, unsigned str);
// Get the vvp_bit4_t version of the value
vvp_bit4_t value() const;
private:
unsigned char value_;
};
extern vvp_scaler_t resolve(vvp_scaler_t a, vvp_scaler_t b);
/*
* This class is a way to carry vectors of strength modeled
* values. The 8 in the name is the number of possible distinct values
* a well defined bit may have. When you add in ambiguous values, the
* number of distinct values span the vvp_scaler_t.
*/
class vvp_vector8_t {
public:
explicit vvp_vector8_t(unsigned size =0);
~vvp_vector8_t();
unsigned size() const { return size_; }
vvp_scaler_t value(unsigned idx) const;
void set_bit(unsigned idx, vvp_scaler_t val);
vvp_vector8_t(const vvp_vector8_t&that);
vvp_vector8_t& operator= (const vvp_vector8_t&that);
private:
unsigned size_;
vvp_scaler_t*bits_;
};
/*
* This class implements a pointer that points to an item within a
* target. The ptr() method returns a pointer to the vvp_net_t, and
* the port() method returns a 0-3 value that selects the input within
* the vvp_net_t. Use this pointer to point only to the inputs of
* vvp_net_t objects. To point to vvp_net_t objects as a whole, use
* vvp_net_t* pointers.
*/
class vvp_net_ptr_t {
public:
vvp_net_ptr_t();
vvp_net_ptr_t(vvp_net_t*ptr, unsigned port);
~vvp_net_ptr_t() { }
vvp_net_t* ptr();
const vvp_net_t* ptr() const;
unsigned port() const;
bool nil() const;
private:
unsigned long bits_;
};
/*
* Alert! Ugly details. Protective clothing recommended!
* The vvp_net_ptr_t encodes the bits of a C pointer, and two bits of
* port identifer into an unsigned long. This works only if vvp_net_t*
* values are always aligned on 4byte boundaries.
*/
inline vvp_net_ptr_t::vvp_net_ptr_t()
{
bits_ = 0;
}
inline vvp_net_ptr_t::vvp_net_ptr_t(vvp_net_t*ptr, unsigned port)
{
bits_ = reinterpret_cast<unsigned long> (ptr);
assert( (bits_ & 3) == 0 );
assert( (port & ~3) == 0 );
bits_ |= port;
}
inline vvp_net_t* vvp_net_ptr_t::ptr()
{
return reinterpret_cast<vvp_net_t*> (bits_ & ~3UL);
}
inline const vvp_net_t* vvp_net_ptr_t::ptr() const
{
return reinterpret_cast<const vvp_net_t*> (bits_ & ~3UL);
}
inline unsigned vvp_net_ptr_t::port() const
{
return bits_ & 3;
}
inline bool vvp_net_ptr_t::nil() const
{
return bits_ == 0;
}
/*
* This is the basic unit of netlist connectivity. It is a fan-in of
* up to 4 inputs, and output pointer, and a pointer to the node's
* functionality.
*
* A net output that is non-nil points to the input of one of its
* destination nets. If there are multiple destinations, then the
* referenced input port points to the next input. For example:
*
* +--+--+--+--+---+
* | | | | | . | Output from this vvp_net_t points to...
* +--+--+--+--+-|-+
* |
* /
* /
* /
* |
* v
* +--+--+--+--+---+
* | | | | | . | ... the fourth input of this vvp_net_t, and...
* +--+--+--+--+-|-+
* | |
* / .
* / .
* | .
* v
* +--+--+--+--+---+
* | | | | | . | ... the third input of this vvp_net_t.
* +--+--+--+--+-|-+
*
* Thus, the fan-in of a vvp_net_t node is limited to 4 inputs, but
* the fan-out is unlimited.
*
* The vvp_send_*() functions take as input a vvp_net_ptr_t and follow
* all the fan-out chain, delivering the specified value.
*/
struct vvp_net_t {
vvp_net_ptr_t port[4];
vvp_net_ptr_t out;
vvp_net_fun_t*fun;
long fun_flags;
};
extern void vvp_send_vec4(vvp_net_ptr_t ptr, vvp_vector4_t val);
extern void vvp_send_vec8(vvp_net_ptr_t ptr, vvp_vector4_t val);
extern void vvp_send_real(vvp_net_ptr_t ptr, double val);
extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
/*
* Instances of this class represent the functionality of a
* node. vvp_net_t objects hold pointers to the vvp_net_fun_t
* associated with it. Objects of this type take inputs that arrive at
* a port and perform some sort of action in response.
*
* Whenever a bit is delivered to a vvp_net_t object, the associated
* vvp_net_fun_t::recv_*() method is invoked with the port pointer and
* the bit value. The port pointer is used to figure out which exact
* input receives the bit.
*
* In this context, a "bit" is the thing that arrives at a single
* input. The bit may be a single data bit, a bit vector, various
* sorts of numbers or aggregate objects.
*/
class vvp_net_fun_t {
public:
vvp_net_fun_t();
virtual ~vvp_net_fun_t();
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
virtual void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
virtual void recv_real(vvp_net_ptr_t port, double bit);
virtual void recv_long(vvp_net_ptr_t port, long bit);
private: // not implemented
vvp_net_fun_t(const vvp_net_fun_t&);
vvp_net_fun_t& operator= (const vvp_net_fun_t&);
};
/* **** Some core net functions **** */
/* vvp_fun_concat
* This node function creates vectors (vvp_vector4_t) from the
* concatenation of the inputs. The inputs (4) may be scalers or other
* vectors. Scalers are turned into vectors of size==1 before
* concatenating.
*/
class vvp_fun_concat : public vvp_net_fun_t {
public:
vvp_fun_concat();
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
};
/* vvp_fun_drive
* This node function takes an input vvp_vector4_t as input, and
* repeats that value as a vvp_vector8_t with all the bits given the
* strength of the drive. This is the way vvp_scaler8_t objects are
* created. Input 0 is the value to be drived (vvp_vector4_t) and
* inputs 1 and two are the strength0 and strength1 values to use. The
* strengths may be taken as constant values, or adjusted as longs
* from the network.
*
* This functor only propagates vvp_vector8_t values.
*/
class vvp_fun_drive : public vvp_net_fun_t {
public:
vvp_fun_drive(vvp_bit4_t init, unsigned str0 =6, unsigned str1 =6);
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
void recv_long(vvp_net_ptr_t port, long bit);
};
/* vvp_fun_part
* This node takes a part select of the input vector. Input 0 is the
* vector to be selected from, and input 1 is the location where the
* select starts. Input 2, which is typically constant, is the width
* of the result.
*/
class vvp_fun_part : public vvp_net_fun_t {
public:
vvp_fun_part(unsigned base, unsigned wid);
~vvp_fun_part();
public:
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
private:
unsigned base_;
unsigned wid_;
};
/* vvp_fun_signal
* This node is the place holder in a vvp network for signals,
* including nets for various sort. The output from a signal is always
* a vector5, use drivers if the context needs vector8 values.
*
* If the signal is a net (i.e. a wire or tri) then this node will
* have an input that is the data source. The data source will connect
* through port-0
*
* If the signal is a reg, then there will be no netlist input, the
* values will be written by behavioral statements. The %set and
* %assign statements will write through port-0
*
* In any case, behavioral code is able to read the value that this
* node last propagated, by using the size(). That is important
* functionality of this node.
*
* Continuous assignments are made through port-1. When a value is
* written here, continuous assign mode is activated, and input
* through port-0 is ignored until continuous assign mode is turned
* off again. Writing into this port can be done in behavioral code
* using the %cassign/v instruction, or can be done by the network by
* hooking the output of a vvp_net_t to this port.
*/
class vvp_fun_signal : public vvp_net_fun_t {
public:
explicit vvp_fun_signal(unsigned wid);
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
void recv_long(vvp_net_ptr_t port, long bit);
// Get information about the vector value.
unsigned size() const;
vvp_bit4_t value(unsigned idx) const;
// Commands
void deassign();
public:
struct __vpiCallback*vpi_callbacks;
private:
vvp_vector4_t bits_;
bool continuous_assign_active_;
private:
void run_vpi_callbacks();
};
/*
* $Log: vvp_net.h,v $
* Revision 1.1 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
*/
#endif