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 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # 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 SHELL = /bin/sh
@ -104,8 +104,8 @@ distclean: clean
do (cd $$dir ; $(MAKE) $@); done do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h 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 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 xnfio.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 \ 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 \ 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include <string> # include <string>
@ -36,6 +36,7 @@ class Design;
class NetAssign_; class NetAssign_;
class NetCAssign; class NetCAssign;
class NetDeassign; class NetDeassign;
class NetForce;
class NetScope; class NetScope;
/* /*
@ -345,7 +346,7 @@ class PForce : public Statement {
explicit PForce(PExpr*l, PExpr*r); explicit PForce(PExpr*l, PExpr*r);
~PForce(); ~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; virtual void dump(ostream&out, unsigned ind) const;
private: private:
@ -456,6 +457,11 @@ class PWhile : public Statement {
/* /*
* $Log: Statement.h,v $ * $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 * Revision 1.40 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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) 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) 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. */ with a simple XOR gate. */
if (top == 1) { if (top == 1) {
NetLogic*tmp = new NetLogic(scope, obj->name(), 3, NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
NetLogic::XNOR); NetLogic::XNOR, 1);
connect(tmp->pin(0), obj->pin_AEB()); connect(tmp->pin(0), obj->pin_AEB());
connect(tmp->pin(1), obj->pin_DataA(0)); connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(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: case NetLogic::AND:
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::BUF); NetLogic::BUF, 1);
break; break;
case NetLogic::NAND: case NetLogic::NAND:
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::NOT); NetLogic::NOT, 1);
break; break;
default: default:
assert(0); assert(0);
@ -480,7 +400,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) { if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope, NetLogic*tmp = new NetLogic(scope,
obj->name(), top, obj->name(), top,
obj->type()); obj->type(), 1);
tmp->rise_time(obj->rise_time()); tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time()); tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time()); tmp->decay_time(obj->decay_time());
@ -597,12 +517,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::OR: case NetLogic::OR:
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::BUF); NetLogic::BUF, 1);
break; break;
case NetLogic::NOR: case NetLogic::NOR:
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::NOT); NetLogic::NOT, 1);
break; break;
default: default:
assert(0); assert(0);
@ -627,7 +547,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) { if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope, NetLogic*tmp = new NetLogic(scope,
obj->name(), top, obj->name(), top,
obj->type()); obj->type(), 1);
tmp->rise_time(obj->rise_time()); tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time()); tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_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) if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::NOT); NetLogic::NOT, 1);
else else
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::BUF); NetLogic::BUF, 1);
tmp->rise_time(obj->rise_time()); tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_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) if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::BUF); NetLogic::BUF, 1);
else else
tmp = new NetLogic(scope, tmp = new NetLogic(scope,
obj->name(), 2, obj->name(), 2,
NetLogic::NOT); NetLogic::NOT, 1);
tmp->rise_time(obj->rise_time()); tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_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()) { if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope, NetLogic*tmp = new NetLogic(scope,
obj->name(), top, obj->name(), top,
obj->type()); obj->type(), 1);
des->add_node(tmp); des->add_node(tmp);
tmp->pin(0).drive0(obj->pin(0).drive0()); tmp->pin(0).drive0(obj->pin(0).drive0());
tmp->pin(0).drive1(obj->pin(0).drive1()); 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) { for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(), NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(), scope->local_symbol(),
3, NetLogic::BUFIF1); 3, NetLogic::BUFIF1, 1);
connect(obj->pin_Result(idx), tmp->pin(0)); connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1)); 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) { for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(), NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(), scope->local_symbol(),
3, NetLogic::BUFIF0); 3, NetLogic::BUFIF0, 1);
connect(obj->pin_Result(idx), tmp->pin(0)); connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1)); connect(obj->pin_Data(idx,0), tmp->pin(1));
@ -1038,6 +958,11 @@ void cprop(Design*des)
/* /*
* $Log: cprop.cc,v $ * $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 * Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -96,8 +96,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")"; o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope()) if (scope())
o << " scope=" << scope()->name(); o << " scope=" << scope()->name();
o << " #(" << rise_time() << "," << fall_time() << "," << o << " #(" << rise_time() << "," << fall_time() << ","
decay_time() << ") init="; << decay_time() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count()
<< " init=";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1) for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << pin(idx-1).get_init(); 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 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_node_pins(o, ind+4);
dump_obj_attr(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 void NetCLShift::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " << 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); 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 void NetMult::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl; 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() o << setw(ind) << "" << "NetBUFZ: " << name()
<< " scope=" << (scope()? scope()->name() : "") << " scope=" << (scope()? scope()->name() : "")
<< " delay=(" << rise_time() << "," << fall_time() << "," << << " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ")" << endl; decay_time() << ") width=" << width() << endl;
dump_node_pins(o, ind+4); 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 void NetConst::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "constant "; o << setw(ind) << "" << "constant " << width_ << "'b";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1) for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
o << value_[idx-1]; o << value_[idx-1];
o << ": " << name() << endl; o << ": " << name() << endl;
dump_node_pins(o, ind+4); 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); 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 void NetRamDq::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): " 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 void NetCAssign::dump(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "cassign " << lval_->name() << " = " o << setw(ind) << "" << "cassign ";
<< name() << ";" << endl; dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
} }
void NetCondit::dump(ostream&o, unsigned ind) const 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 void NetDeassign::dump(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "deassign " << lval_->name() << "; " o << setw(ind) << "" << "deassign ";
<< "/* " << get_line() << " */" << endl; dump_lval(o);
o << "; /* " << get_line() << " */" << endl;
} }
void NetDisable::dump(ostream&o, unsigned ind) const 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 void NetForce::dump(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "force " << lval_->name() << " = " o << setw(ind) << "" << "force ";
<< name() << ";" << endl; dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
} }
void NetForever::dump(ostream&o, unsigned ind) const 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 void NetRelease::dump(ostream&o, unsigned ind) const
{ {
if (lval_) o << setw(ind) << "" << "release ";
o << setw(ind) << "" << "release " << lval_->name() << "; " dump_lval(o);
<< "/* " << get_line() << " */" << endl; o << "; /* " << get_line() << " */" << endl;
else
o << setw(ind) << "" << "release (null); "
<< "/* " << get_line() << " */" << endl;
} }
void NetRepeat::dump(ostream&o, unsigned ind) const void NetRepeat::dump(ostream&o, unsigned ind) const
@ -995,7 +993,7 @@ void NetESignal::dump(ostream&o) const
{ {
if (has_sign()) if (has_sign())
o << "+"; o << "+";
o << name() << "[" << msi_<<":"<<lsi_ << "]"; o << name() << "[" << msi()<<":"<<lsi() << "]";
} }
void NetEBitSel::dump(ostream&o) const void NetEBitSel::dump(ostream&o) const
@ -1089,6 +1087,11 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $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 * Revision 1.149 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -87,7 +87,7 @@ NetESFunc* NetESFunc::dup_expr() const
NetESignal* NetESignal::dup_expr() const NetESignal* NetESignal::dup_expr() const
{ {
NetESignal*tmp = new NetESignal(net_, msi_, lsi_); NetESignal*tmp = new NetESignal(net_);
assert(tmp); assert(tmp);
tmp->expr_width(expr_width()); tmp->expr_width(expr_width());
return tmp; return tmp;
@ -143,6 +143,11 @@ NetEVariable* NetEVariable::dup_expr() const
/* /*
* $Log: dup_expr.cc,v $ * $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 * Revision 1.18 2004/06/17 16:06:18 steve
* Help system function signedness survive elaboration. * Help system function signedness survive elaboration.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -699,10 +699,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
delete msn; delete msn;
return 0; return 0;
} }
#if 0
NetESignal*tmp = new NetESignal(net, NetESignal*tmp = new NetESignal(net,
net->sb_to_idx(msv), net->sb_to_idx(msv),
net->sb_to_idx(lsv)); 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); tmp->set_line(*this);
return tmp; return tmp;
@ -735,7 +740,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp; return tmp;
} }
#if 0
NetESignal*tmp = new NetESignal(net, idx, idx); 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); tmp->set_line(*this);
return tmp; return tmp;
@ -1005,6 +1016,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/* /*
* $Log: elab_expr.cc,v $ * $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 * Revision 1.91 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -283,7 +283,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
converted to normalized form so is relative the converted to normalized form so is relative the
variable pins. */ variable pins. */
if ((wid + loff) > reg->pin_count()) { if ((wid + loff) > reg->vector_width()) {
cerr << get_line() << ": error: bit/part select " cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]" << reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl; << " is out of range." << endl;
@ -293,8 +293,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
lv = new NetAssign_(reg); lv = new NetAssign_(reg);
lv->set_part(loff, wid); 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 $ * $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 * Revision 1.29 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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 /* The owidth is the output width of the lpm_add_sub
device. If the desired width is greater then the width of device. If the desired width is greater then the width of
the operands, then widen the adder and let code below pad the operands, then widen the adder and let code below pad
the operands. If this is an adder, we can take advantage of the operands. */
the carry bit. */
unsigned owidth = width; unsigned owidth = width;
switch (op_) { switch (op_) {
case '+': case '+':
if (lwidth > owidth) { if (lwidth > owidth) {
owidth = lwidth; owidth = lwidth;
width = lwidth-1; width = lwidth;
} }
break; break;
case '-': case '-':
@ -228,18 +227,21 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
osig = new NetNet(scope, scope->local_symbol(), osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, owidth); NetNet::WIRE, owidth);
osig->local_flag(true); 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); NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), width);
// Connect the adder to the various parts. // Connect the adder to the various parts.
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) connect(lsig->pin(0), adder->pin_DataA());
connect(lsig->pin(idx), adder->pin_DataA(idx)); connect(rsig->pin(0), adder->pin_DataB());
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) connect(osig->pin(0), adder->pin_Result());
connect(rsig->pin(idx), adder->pin_DataB(idx)); #ifdef XXXX
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(osig->pin(idx), adder->pin_Result(idx));
if (owidth > width) if (owidth > width)
connect(osig->pin(width), adder->pin_Cout()); connect(osig->pin(width), adder->pin_Cout());
#endif
NetNode*gate = adder; NetNode*gate = adder;
gate->rise_time(rise); gate->rise_time(rise);
gate->fall_time(fall); 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) { for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(), NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, gtype); 3, gtype, 1);
connect(gate->pin(1), lsig->pin(idx)); connect(gate->pin(1), lsig->pin(idx));
connect(gate->pin(2), rsig->pin(idx)); connect(gate->pin(2), rsig->pin(idx));
connect(gate->pin(0), osig->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; NetLogic*ones_gate = 0;
if (zeros > 0) if (zeros > 0)
zero_gate = new NetLogic(scope, zero_gate = new NetLogic(scope,
scope->local_symbol(), zeros + 1, scope->local_symbol(), zeros + 1,
(op_code == 'n') ? NetLogic::OR : NetLogic::NOR); (op_code == 'n') ? NetLogic::OR : NetLogic::NOR, 1);
if (ones > 0) if (ones > 0)
ones_gate = new NetLogic(scope, ones_gate = new NetLogic(scope,
scope->local_symbol(), ones + 1, scope->local_symbol(), ones + 1,
(op_code == 'n') ? NetLogic::NAND : NetLogic::AND); (op_code == 'n') ? NetLogic::NAND : NetLogic::AND, 1);
unsigned zidx = 0; unsigned zidx = 0;
unsigned oidx = 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)); connect(and_sig->pin(1), ones_gate->pin(0));
NetLogic*and_gate = new NetLogic(scope, NetLogic*and_gate = new NetLogic(scope,
scope->local_symbol(), 3, 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(0), osig->pin(0));
connect(and_gate->pin(1), and_sig->pin(0)); connect(and_gate->pin(1), and_sig->pin(0));
connect(and_gate->pin(2), and_sig->pin(1)); 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(), gate = new NetLogic(scope, scope->local_symbol(),
1+dwidth, 1+dwidth,
(op_ == 'E')? NetLogic::AND : NetLogic::NAND); (op_ == 'E')? NetLogic::AND : NetLogic::NAND, 1);
connect(gate->pin(0), osig->pin(0)); connect(gate->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) { for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
NetCaseCmp*cmp = new NetCaseCmp(scope, 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. */ single XNOR gate. This is easy and direct. */
if (dwidth == 1) { if (dwidth == 1) {
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR); 3, NetLogic::XNOR, 1);
connect(gate->pin(0), osig->pin(0)); connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0)); connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->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. */ single XOR gate. This is easy and direct. */
if (dwidth == 1) { if (dwidth == 1) {
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR); 3, NetLogic::XOR, 1);
connect(gate->pin(0), osig->pin(0)); connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0)); connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0)); connect(gate->pin(2), rsig->pin(0));
@ -899,11 +901,11 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
switch (op_) { switch (op_) {
case 'a': case 'a':
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::AND); 3, NetLogic::AND, 1);
break; break;
case 'o': case 'o':
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::OR); 3, NetLogic::OR, 1);
break; break;
default: default:
assert(0); 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... // The first OR gate returns 1 if the left value is true...
if (lsig->pin_count() > 1) { if (lsig->pin_count() > 1) {
gate_t = new NetLogic(scope, scope->local_symbol(), 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) for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(gate_t->pin(idx+1), lsig->pin(idx)); 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... // The second OR gate returns 1 if the right value is true...
if (rsig->pin_count() > 1) { if (rsig->pin_count() > 1) {
gate_t = new NetLogic(scope, scope->local_symbol(), 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) for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(gate_t->pin(idx+1), rsig->pin(idx)); connect(gate_t->pin(idx+1), rsig->pin(idx));
connect(gate->pin(2), gate_t->pin(0)); 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. */ signal for the part select to be correct. */
if (! (sig->sb_is_valid(mbit) && sig->sb_is_valid(lbit))) { if (! (sig->sb_is_valid(mbit) && sig->sb_is_valid(lbit))) {
cerr << get_line() << ": error: bit/part select [" cerr << get_line() << ": error: bit/part select ["
<< mval->as_long() << ":" << lval->as_long() << mbit << ":" << lbit
<< "] out of range for " << sig->name() << endl; << "] out of range for " << sig->name() << endl;
des->errors += 1; des->errors += 1;
return sig; return sig;
@ -1619,7 +1621,19 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
unsigned part_count = midx-lidx+1; 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; sig = tmp;
@ -1632,15 +1646,35 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
} }
assert(mval); assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long()); long mbit = mval->as_long();
if (idx >= sig->pin_count()) {
cerr << get_line() << ": error: index " << sig->name() << /* Check that the part select is valid. Both ends of the
"[" << mval->as_long() << "] out of range." << endl; 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; 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; 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 * 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, NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const bool implicit_net_ok) const
@ -1706,7 +1743,7 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
assert(scope); assert(scope);
svector<NetNet*>nets (parms_.count()); svector<NetNet*>nets (parms_.count());
unsigned pins = 0; unsigned width = 0;
unsigned errors = 0; unsigned errors = 0;
if (repeat_) { if (repeat_) {
@ -1718,6 +1755,12 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
/* Elaborate the operands of the concatenation. */ /* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) { 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) { if (parms_[idx] == 0) {
cerr << get_line() << ": error: Empty expressions " cerr << get_line() << ": error: Empty expressions "
<< "not allowed in concatenations." << endl; << "not allowed in concatenations." << endl;
@ -1730,7 +1773,7 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
if (nets[idx] == 0) if (nets[idx] == 0)
errors += 1; errors += 1;
else else
pins += nets[idx]->pin_count(); width += nets[idx]->vector_width();
} }
/* If any of the sub expressions failed to elaborate, then /* 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 /* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant, concat operator from most significant to least significant,
which is opposite from how they are given in the list. */ which is the order they are given in the concat list. */
NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pins); NetNet::IMPLICIT, width);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1]; if (debug_elaborate) {
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) { cerr << get_line() << ": debug: Generating part selects "
connect(osig->pin(pins), cur->pin(pin)); << "to connect input l-value to subexpressions."
pins += 1; << 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); osig->local_flag(true);
return osig; return osig;
} }
@ -2046,18 +2103,15 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
break; break;
} }
verinum num(top_v, net->pin_count()); verinum num(top_v, net->vector_width());
unsigned idx; unsigned idx;
for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1) for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1)
num.set(idx, value_->get(idx)); num.set(idx, value_->get(idx));
NetConst*tmp = new NetConst(scope, scope->local_symbol(), NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
num); tmp->pin(0).drive0(drive0);
for (idx = 0 ; idx < net->pin_count() ; idx += 1) { tmp->pin(0).drive1(drive1);
tmp->pin(idx).drive0(drive0); connect(net->pin(0), tmp->pin(0));
tmp->pin(idx).drive1(drive1);
connect(net->pin(idx), tmp->pin(idx));
}
des->add_node(tmp); des->add_node(tmp);
return net; return net;
@ -2073,8 +2127,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
net->set_signed(value_->has_sign()); net->set_signed(value_->has_sign());
NetConst*tmp = new NetConst(scope, scope->local_symbol(), NetConst*tmp = new NetConst(scope, scope->local_symbol(),
*value_); *value_);
for (unsigned idx = 0 ; idx < value_->len() ; idx += 1) connect(net->pin(0), tmp->pin(0));
connect(net->pin(idx), tmp->pin(idx));
des->add_node(tmp); des->add_node(tmp);
return net; return net;
@ -2116,8 +2169,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
NetNet::IMPLICIT, width); NetNet::IMPLICIT, width);
net->local_flag(true); net->local_flag(true);
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num); NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
for (unsigned idx = 0 ; idx < width ; idx += 1) connect(net->pin(0), tmp->pin(0));
connect(net->pin(idx), tmp->pin(idx));
des->add_node(tmp); des->add_node(tmp);
return net; return net;
@ -2224,7 +2276,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
if (expr_sig->pin_count() > 1) { if (expr_sig->pin_count() > 1) {
NetLogic*log = new NetLogic(scope, scope->local_symbol(), NetLogic*log = new NetLogic(scope, scope->local_symbol(),
expr_sig->pin_count()+1, expr_sig->pin_count()+1,
NetLogic::OR); NetLogic::OR, 1);
for (unsigned idx = 0; idx < expr_sig->pin_count(); idx += 1) for (unsigned idx = 0; idx < expr_sig->pin_count(); idx += 1)
connect(log->pin(idx+1), expr_sig->pin(idx)); connect(log->pin(idx+1), expr_sig->pin(idx));
@ -2284,7 +2336,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
NetNet::WIRE, dwidth); NetNet::WIRE, dwidth);
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) { 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->rise_time(rise);
tmpz->fall_time(fall); tmpz->fall_time(fall);
tmpz->decay_time(decay); tmpz->decay_time(decay);
@ -2388,7 +2440,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
sig->local_flag(true); sig->local_flag(true);
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) { for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) {
gate = new NetLogic(scope, scope->local_symbol(), 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(1), sub_sig->pin(idx));
connect(gate->pin(0), sig->pin(idx)); connect(gate->pin(0), sig->pin(idx));
des->add_node(gate); des->add_node(gate);
@ -2427,7 +2479,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
case 1: case 1:
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
2, NetLogic::BUF); 2, NetLogic::BUF, 1);
connect(gate->pin(0), sig->pin(0)); connect(gate->pin(0), sig->pin(0));
connect(gate->pin(1), sub_sig->pin(0)); connect(gate->pin(1), sub_sig->pin(0));
des->add_node(gate); des->add_node(gate);
@ -2438,7 +2490,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
case 2: case 2:
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
2, NetLogic::BUF); 2, NetLogic::BUF, 1);
connect(gate->pin(0), sig->pin(0)); connect(gate->pin(0), sig->pin(0));
connect(gate->pin(1), sub_sig->pin(0)); connect(gate->pin(1), sub_sig->pin(0));
des->add_node(gate); des->add_node(gate);
@ -2447,7 +2499,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
gate->decay_time(decay); gate->decay_time(decay);
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR); 3, NetLogic::XOR, 1);
connect(gate->pin(0), sig->pin(1)); connect(gate->pin(0), sig->pin(1));
connect(gate->pin(1), sub_sig->pin(0)); connect(gate->pin(1), sub_sig->pin(0));
connect(gate->pin(2), sub_sig->pin(1)); connect(gate->pin(2), sub_sig->pin(1));
@ -2464,11 +2516,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
des->add_node(sub); des->add_node(sub);
for (unsigned idx = 0 ; idx < sig->pin_count(); idx += 1) connect(sig->pin(0), sub->pin_Result());
connect(sig->pin(idx), sub->pin_Result(idx)); connect(sub_sig->pin(0), sub->pin_DataB());
for (unsigned idx = 0; idx < sub_sig->pin_count(); idx += 1)
connect(sub_sig->pin(idx), sub->pin_DataB(idx));
verinum tmp_num (verinum::V0, sub->width(), true); verinum tmp_num (verinum::V0, sub->width(), true);
NetConst*tmp_con = new NetConst(scope, NetConst*tmp_con = new NetConst(scope,
@ -2481,10 +2530,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
sub_sig->pin_count()); sub_sig->pin_count());
tmp_sig->local_flag(true); tmp_sig->local_flag(true);
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) { connect(tmp_sig->pin(0), sub->pin_DataA());
connect(tmp_sig->pin(idx), sub->pin_DataA(idx)); connect(tmp_sig->pin(0), tmp_con->pin(0));
connect(tmp_sig->pin(idx), tmp_con->pin(idx));
}
break; break;
} }
break; break;
@ -2497,7 +2544,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE); sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
sig->local_flag(true); sig->local_flag(true);
gate = new NetLogic(scope, scope->local_symbol(), 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)); connect(gate->pin(0), sig->pin(0));
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
connect(gate->pin(idx+1), sub_sig->pin(idx)); 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 $ * $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 * Revision 1.138 2004/10/04 03:09:38 steve
* Fix excessive error message. * Fix excessive error message.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -610,6 +610,12 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
} else { } else {
perm_string name = lex_strings.make(hname_.peek_tail_name()); 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); NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
sig->set_line(*this); sig->set_line(*this);
sig->port_type(port_type_); sig->port_type(port_type_);
@ -623,6 +629,11 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
/* /*
* $Log: elab_sig.cc,v $ * $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 * Revision 1.36 2004/09/27 22:34:10 steve
* Cleanup and factoring of autoconf. * Cleanup and factoring of autoconf.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -91,6 +91,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
return; 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 /* Handle the special case that the rval is simply an
identifier. Get the rval as a NetNet, then use NetBUFZ 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 direct drivers. This is how I attach strengths to the
assignment operation. */ assignment operation. */
if (const PEIdent*id = dynamic_cast<const PEIdent*>(pin(1))) { 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, 0, 0, 0, Link::STRONG,
Link::STRONG); Link::STRONG);
if (rid == 0) { if (rid == 0) {
@ -107,7 +113,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
} }
assert(rid); assert(rid);
assert(rid->pin_count() == 1);
/* If the right hand net is the same type as the left /* If the right hand net is the same type as the left
side net (i.e., WIRE/WIRE) then it is enough to just 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 is not as wide as the l-value by padding with a
constant-0. */ constant-0. */
unsigned cnt = lval->pin_count(); unsigned cnt = lval->vector_width();
if (rid->pin_count() < cnt) if (rid->vector_width() < cnt)
cnt = rid->pin_count(); cnt = rid->pin_count();
bool need_driver_flag = false; bool need_driver_flag = false;
/* If the device is linked to itself, a driver is /* If the device is linked to itself, a driver is
needed. Should I print a warning here? */ needed. Should I print a warning here? */
for (unsigned idx = 0 ; idx < cnt ; idx += 1) { if (lval->pin(0) .is_linked (rid->pin(0)))
if (lval->pin(idx) .is_linked (rid->pin(idx))) { need_driver_flag = true;
need_driver_flag = true;
break;
}
}
/* If the nets are different type (i.e., reg vs. tri) then /* If the nets are different type (i.e., reg vs. tri) then
a driver is needed. */ 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 /* If there is a strength to be carried, then I need a
driver to carry that strength. */ driver to carry that strength. */
for (unsigned idx = 0 ; idx < cnt ; idx += 1) { if (rid->pin(0).drive0() != drive0)
if (rid->pin(idx).drive0() != drive0) { need_driver_flag = true;
need_driver_flag = true;
break; if (rid->pin(0).drive1() != drive1)
} need_driver_flag = true;
if (rid->pin(idx).drive1() != drive1) {
need_driver_flag = true;
break;
}
}
if (! need_driver_flag) { if (! need_driver_flag) {
/* Don't need a driver, presumably because the /* 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 hook things up. If the r-value is too narrow
for the l-value, then sign extend it or zero for the l-value, then sign extend it or zero
extend it, whichever makes sense. */ extend it, whichever makes sense. */
unsigned idx; connect(lval->pin(0), rid->pin(0));
for (idx = 0 ; idx < cnt; idx += 1)
connect(lval->pin(idx), rid->pin(idx));
if (cnt < lval->pin_count()) { if (cnt < lval->pin_count()) {
#if 0
if (lval->get_signed() && rid->get_signed()) { if (lval->get_signed() && rid->get_signed()) {
for (idx = cnt for (idx = cnt
; idx < lval->pin_count() ; idx < lval->pin_count()
@ -184,45 +181,28 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
; idx += 1) ; idx += 1)
connect(lval->pin(idx), tmp->pin(idx-cnt)); connect(lval->pin(idx), tmp->pin(idx-cnt));
} }
#else
cerr << get_line() << ": internal error: "
<< "Forgot how to handle mismatched widths."
<< endl;
#endif
} }
} else { } else {
/* Do need a driver. Use BUFZ objects to carry the /* Do need a driver. Use BUFZ objects to carry the
strength and delays. */ 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()) { NetBUFZ*dev = new NetBUFZ(scope, scope->local_symbol(),
if (lval->get_signed() && rid->get_signed()) { rid->vector_width());
for (idx = cnt connect(lval->pin(0), dev->pin(0));
; idx < lval->pin_count() connect(rid->pin(0), dev->pin(1));
; idx += 1) dev->rise_time(rise_time);
connect(lval->pin(idx), lval->pin(cnt-1)); 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; 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 which are going to be attached to the last gate before the
generated NetNet. */ generated NetNet. */
NetNet*rval = pin(1)->elaborate_net(des, scope, NetNet*rval = pin(1)->elaborate_net(des, scope,
lval->pin_count(), lval->vector_width(),
rise_time, fall_time, decay_time, rise_time, fall_time, decay_time,
drive0, drive1); drive0, drive1);
if (rval == 0) { if (rval == 0) {
@ -243,17 +223,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
} }
assert(lval && rval); assert(lval && rval);
assert(rval->pin_count() == 1);
/* If the r-value insists on being smaller then the l-value /* If the r-value insists on being smaller then the l-value
(perhaps it is explicitly sized) the pad it out to be the (perhaps it is explicitly sized) the pad it out to be the
right width so that something is connected to all the bits right width so that something is connected to all the bits
of the l-value. */ of the l-value. */
if (lval->pin_count() > rval->pin_count()) if (lval->vector_width() > rval->vector_width())
rval = pad_to_width(des, rval, lval->pin_count()); rval = pad_to_width(des, rval, lval->vector_width());
for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) connect(lval->pin(0), rval->pin(0));
connect(lval->pin(idx), rval->pin(idx));
if (lval->local_flag()) if (lval->local_flag())
delete lval; delete lval;
@ -355,75 +334,75 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
switch (type()) { switch (type()) {
case AND: case AND:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::AND); NetLogic::AND, 1);
break; break;
case BUF: case BUF:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUF); NetLogic::BUF, 1);
break; break;
case BUFIF0: case BUFIF0:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUFIF0); NetLogic::BUFIF0, 1);
break; break;
case BUFIF1: case BUFIF1:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::BUFIF1); NetLogic::BUFIF1, 1);
break; break;
case NAND: case NAND:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NAND); NetLogic::NAND, 1);
break; break;
case NMOS: case NMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NMOS); NetLogic::NMOS, 1);
break; break;
case NOR: case NOR:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOR); NetLogic::NOR, 1);
break; break;
case NOT: case NOT:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOT); NetLogic::NOT, 1);
break; break;
case NOTIF0: case NOTIF0:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOTIF0); NetLogic::NOTIF0, 1);
break; break;
case NOTIF1: case NOTIF1:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::NOTIF1); NetLogic::NOTIF1, 1);
break; break;
case OR: case OR:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::OR); NetLogic::OR, 1);
break; break;
case RNMOS: case RNMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::RNMOS); NetLogic::RNMOS, 1);
break; break;
case RPMOS: case RPMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::RPMOS); NetLogic::RPMOS, 1);
break; break;
case PMOS: case PMOS:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PMOS); NetLogic::PMOS, 1);
break; break;
case PULLDOWN: case PULLDOWN:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PULLDOWN); NetLogic::PULLDOWN, 1);
break; break;
case PULLUP: case PULLUP:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::PULLUP); NetLogic::PULLUP, 1);
break; break;
case XNOR: case XNOR:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XNOR); NetLogic::XNOR, 1);
break; break;
case XOR: case XOR:
cur[idx] = new NetLogic(scope, inm, pin_count(), cur[idx] = new NetLogic(scope, inm, pin_count(),
NetLogic::XOR); NetLogic::XOR, 1);
break; break;
default: default:
cerr << get_line() << ": internal error: unhandled " cerr << get_line() << ": internal error: unhandled "
@ -1712,29 +1691,36 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
return block; 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* PCAssign::elaborate(Design*des, NetScope*scope) const
{ {
NetCAssign*dev = 0;
assert(scope); assert(scope);
NetNet*lval = lval_->elaborate_anet(des, scope); NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0) if (lval == 0)
return 0; return 0;
NetNet*rval = expr_->elaborate_net(des, scope, lval->pin_count(), NetExpr*rexp = elab_and_eval(des, scope, expr_);
0, 0, 0); if (rexp == 0)
if (rval == 0)
return 0; return 0;
if (rval->pin_count() < lval->pin_count()) dev = new NetCAssign(lval, rexp);
rval = pad_to_width(des, rval, lval->pin_count());
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); 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; return dev;
} }
@ -1742,7 +1728,7 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
{ {
assert(scope); assert(scope);
NetNet*lval = lval_->elaborate_anet(des, scope); NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0) if (lval == 0)
return 0; return 0;
@ -2225,28 +2211,30 @@ NetProc* PForever::elaborate(Design*des, NetScope*scope) const
return proc; return proc;
} }
NetProc* PForce::elaborate(Design*des, NetScope*scope) const NetForce* PForce::elaborate(Design*des, NetScope*scope) const
{ {
NetForce*dev = 0;
assert(scope); assert(scope);
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0); NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0) if (lval == 0)
return 0; return 0;
NetNet*rval = expr_->elaborate_net(des, scope, lval->pin_count(), NetExpr*rexp = elab_and_eval(des, scope, expr_);
0, 0, 0); if (rexp == 0)
if (rval == 0)
return 0; return 0;
if (rval->pin_count() < lval->pin_count()) dev = new NetForce(lval, rexp);
rval = pad_to_width(des, rval, lval->pin_count());
NetForce* dev = new NetForce(scope, scope->local_symbol(), lval); if (debug_elaborate) {
des->add_node(dev); cerr << get_line() << ": debug: ELaborate force,"
<< " lval width=" << lval->lwidth()
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1) << " rval width=" << rexp->expr_width()
connect(dev->pin(idx), rval->pin(idx)); << " rval=" << *rexp
<< endl;
}
dev->set_line(*this);
return dev; return dev;
} }
@ -2398,7 +2386,7 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
{ {
assert(scope); assert(scope);
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0); NetAssign_*lval = lval_->elaborate_lval(des, scope);
if (lval == 0) if (lval == 0)
return 0; return 0;
@ -2769,96 +2757,10 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.308 2004/10/04 01:10:52 steve * Revision 1.309 2004/12/11 02:31:25 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -63,12 +63,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
return true; 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 bool NetCLShift::emit_node(struct target_t*tgt) const
{ {
tgt->lpm_clshift(this); tgt->lpm_clshift(this);
@ -98,12 +92,6 @@ bool NetFF::emit_node(struct target_t*tgt) const
return true; 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 bool NetModulo::emit_node(struct target_t*tgt) const
{ {
tgt->lpm_modulo(this); tgt->lpm_modulo(this);
@ -122,6 +110,11 @@ bool NetMux::emit_node(struct target_t*tgt) const
return true; 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 bool NetRamDq::emit_node(struct target_t*tgt) const
{ {
tgt->lpm_ram_dq(this); tgt->lpm_ram_dq(this);
@ -511,6 +504,11 @@ bool emit(const Design*des, const char*type)
/* /*
* $Log: emit.cc,v $ * $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 * Revision 1.77 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * 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 * Revision 1.71 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to * Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -60,11 +60,9 @@ NetNet* NetEBAdd::synthesize(Design*des)
perm_string oname = osig->scope()->local_symbol(); perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width); NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
for (unsigned idx = 0 ; idx < width; idx += 1) { connect(lsig->pin(0), adder->pin_DataA());
connect(lsig->pin(idx), adder->pin_DataA(idx)); connect(rsig->pin(0), adder->pin_DataB());
connect(rsig->pin(idx), adder->pin_DataB(idx)); connect(osig->pin(0), adder->pin_Result());
connect(osig->pin(idx), adder->pin_Result(idx));
}
des->add_node(adder); des->add_node(adder);
switch (op()) { switch (op()) {
@ -136,19 +134,19 @@ NetNet* NetEBBits::synthesize(Design*des)
switch (op()) { switch (op()) {
case '&': case '&':
gate = new NetLogic(scope, oname, 3, NetLogic::AND); gate = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
break; break;
case '|': case '|':
gate = new NetLogic(scope, oname, 3, NetLogic::OR); gate = new NetLogic(scope, oname, 3, NetLogic::OR, 1);
break; break;
case '^': case '^':
gate = new NetLogic(scope, oname, 3, NetLogic::XOR); gate = new NetLogic(scope, oname, 3, NetLogic::XOR, 1);
break; break;
case 'O': case 'O':
gate = new NetLogic(scope, oname, 3, NetLogic::NOR); gate = new NetLogic(scope, oname, 3, NetLogic::NOR, 1);
break; break;
case 'X': case 'X':
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR); gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, 1);
break; break;
default: default:
assert(0); assert(0);
@ -191,12 +189,12 @@ NetNet* NetEBComp::synthesize(Design*des)
case 'e': case 'e':
case 'E': case 'E':
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR); lsig->pin_count()+1, NetLogic::NOR, 1);
break; break;
case 'n': case 'n':
case 'N': case 'N':
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR); lsig->pin_count()+1, NetLogic::OR, 1);
break; break;
case '>': case '>':
@ -205,11 +203,11 @@ NetNet* NetEBComp::synthesize(Design*des)
happen. */ happen. */
if (rcon) { if (rcon) {
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR); lsig->pin_count()+1, NetLogic::OR, 1);
} else { } else {
assert(0); assert(0);
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR); lsig->pin_count()+1, NetLogic::NOR, 1);
} }
break; break;
@ -217,11 +215,11 @@ NetNet* NetEBComp::synthesize(Design*des)
/* 0 < sig is handled like sig > 0. */ /* 0 < sig is handled like sig > 0. */
if (! rcon) { if (! rcon) {
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::OR); lsig->pin_count()+1, NetLogic::OR, 1);
} else { } else {
assert(0); assert(0);
gate = new NetLogic(scope, scope->local_symbol(), gate = new NetLogic(scope, scope->local_symbol(),
lsig->pin_count()+1, NetLogic::NOR); lsig->pin_count()+1, NetLogic::NOR, 1);
} }
break; break;
@ -258,7 +256,7 @@ NetNet* NetEBComp::synthesize(Design*des)
operation. Make an XNOR gate instead of a comparator. */ operation. Make an XNOR gate instead of a comparator. */
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) { if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(), 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(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0)); connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->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. */ an XOR instead of an XNOR gate. */
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) { if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(), 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(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0)); connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0)); connect(gate->pin(2), rsig->pin(0));
@ -449,7 +447,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetLogic*olog = new NetLogic(scope, oname, NetLogic*olog = new NetLogic(scope, oname,
lsig->pin_count()+rsig->pin_count()+1, lsig->pin_count()+rsig->pin_count()+1,
NetLogic::OR); NetLogic::OR, 1);
connect(osig->pin(0), olog->pin(0)); connect(osig->pin(0), olog->pin(0));
@ -471,7 +469,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetLogic*olog; NetLogic*olog;
perm_string oname = scope->local_symbol(); 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)); connect(osig->pin(0), olog->pin(0));
des->add_node(olog); des->add_node(olog);
@ -669,7 +667,7 @@ NetNet* NetEUBits::synthesize(Design*des)
switch (op()) { switch (op()) {
case '~': case '~':
gate = new NetLogic(scope, oname, 2, NetLogic::NOT); gate = new NetLogic(scope, oname, 2, NetLogic::NOT, 1);
break; break;
default: default:
assert(0); assert(0);
@ -702,32 +700,32 @@ NetNet* NetEUReduce::synthesize(Design*des)
case 'N': case 'N':
case '!': case '!':
gate = new NetLogic(scope, oname, isig->pin_count()+1, gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NOR); NetLogic::NOR, 1);
break; break;
case '&': case '&':
gate = new NetLogic(scope, oname, isig->pin_count()+1, gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::AND); NetLogic::AND, 1);
break; break;
case '|': case '|':
gate = new NetLogic(scope, oname, isig->pin_count()+1, gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::OR); NetLogic::OR, 1);
break; break;
case '^': case '^':
gate = new NetLogic(scope, oname, isig->pin_count()+1, gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XOR); NetLogic::XOR, 1);
break; break;
case 'A': case 'A':
gate = new NetLogic(scope, oname, isig->pin_count()+1, gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NAND); NetLogic::NAND, 1);
break; break;
case 'X': case 'X':
gate = new NetLogic(scope, oname, isig->pin_count()+1, gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XNOR); NetLogic::XNOR, 1);
break; break;
default: default:
@ -854,27 +852,16 @@ NetNet* NetETernary::synthesize(Design *des)
*/ */
NetNet* NetESignal::synthesize(Design*des) NetNet* NetESignal::synthesize(Design*des)
{ {
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1))) return net_;
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;
} }
/* /*
* $Log: expr_synth.cc,v $ * $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 * Revision 1.59 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets. * Implement signed divide and signed right shift in nets.
* *

View File

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

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -231,6 +231,7 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_MOD = 13, IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4, IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5, IVL_LPM_MUX = 5,
IVL_LPM_PART = 15, /* part select */
IVL_LPM_SHIFTL = 6, IVL_LPM_SHIFTL = 6,
IVL_LPM_SHIFTR = 7, IVL_LPM_SHIFTR = 7,
IVL_LPM_SUB = 8, 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 unsigned ivl_design_consts(ivl_design_t des);
extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx); extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
/* /* VECTOR CONSTANTS
* These methods apply to ivl_net_const_t objects. * 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 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 ivl_nexus_t ivl_const_nex(ivl_net_const_t net);
extern unsigned ivl_const_pins(ivl_net_const_t net);
extern int ivl_const_signed(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 /* 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 * the ivl_net_logic_t can represent. The various functions then
* provide access to the bits of information for a given logic device. * 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 * ivl_logic_type
* This method returns the type of logic gate that the cookie * This method returns the type of logic gate that the node
* represents. * represents. The logic type implies the meaning of the various pins.
* *
* ivl_logic_name (obsolete) * ivl_logic_name (obsolete)
* This method returns the complete name of the logic gate. Every * 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 * together, then these values are the same. Use the nexus
* functions to find other pins that are connected to this 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) * ivl_logic_attr (obsolete)
* Return the value of a specific attribute, given the key name as * Return the value of a specific attribute, given the key name as
* a string. If the key is not defined, then return 0 (null). * 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 * These functions apply to a subset of the LPM devices, or may have
* varying meaning depending on the device: * 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 * ivl_lpm_data
* Return the input data nexus for device types that have a single * 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 * 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_clr(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_sync_set(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); 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 */ /* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */ /* IVL_LPM_UFUNC */
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net); extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */ /* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); 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); extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */ /* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
/* IVL_LPM_MUX IVL_LPM_UFUNC */ /* 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); extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
/* IVL_LPM_UFUNC */ /* IVL_LPM_UFUNC */
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx); 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_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
IVL_LPM_UFUNC */ IVL_LPM_SUB IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX IVL_LPM_RAM */ /* IVL_LPM_MUX IVL_LPM_RAM */
extern unsigned ivl_lpm_selects(ivl_lpm_t net); 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 * part select so that ivl_lval_pin(net, 0) is the proper bit in the
* signal. * 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 * ivl_lval_mux
* If the l-value includes a bit select expression, this method * If the l-value includes a bit select expression, this method
* returns an ivl_expr_t that represents that * 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. * 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_mux(ivl_lval_t net);
extern ivl_expr_t ivl_lval_idx(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_memory_t ivl_lval_mem(ivl_lval_t net);
extern ivl_variable_t ivl_lval_var(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 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 unsigned ivl_lval_pins(ivl_lval_t net);
extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx); 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 /* NEXUS
* connections of signals and nodes is handled by single-bit * 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 * Signals have a name (obviously) and types. A signal may also be
* signed or unsigned. * signed or unsigned.
* *
* ivl_signal_pins * ivl_signal_pins (replace these with ivl_signal_nex)
* ivl_signal_pin * ivl_signal_pin
* The ivl_signal_pin function returns the nexus connected to the * 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 * 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. * 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_msb
* ivl_signal_lsb * ivl_signal_lsb
* ivl_signal_width
* These functions return the left and right indices, respectively, * These functions return the left and right indices, respectively,
* of the signal. If the signal is a scalar, both return 0. However, * 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 * 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. * key does not exist, the function returns 0.
*/ */
extern ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx); extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net);
extern unsigned ivl_signal_pins(ivl_signal_t net);
extern int ivl_signal_msb(ivl_signal_t net); extern int ivl_signal_msb(ivl_signal_t net);
extern int ivl_signal_lsb(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 ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
extern int ivl_signal_signed(ivl_signal_t net); extern int ivl_signal_signed(ivl_signal_t net);
extern int ivl_signal_integer(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 unsigned ivl_signal_attr_cnt(ivl_signal_t net);
extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx); 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 * 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 * one type of statement, so the comment in front of them tells which
* statement types can be passed to the function. * statement types can be passed to the function.
* *
* FUNCTION SUMMARY:
*
* ivl_stmt_block_scope * ivl_stmt_block_scope
* If the block is named, then there is a scope associated with * If the block is named, then there is a scope associated with
* this. The code generator may need to know this in order to * this. The code generator may need to know this in order to
* handle disable statements. * 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 */ /* IVL_ST_BLOCK, IVL_ST_FORK */
@ -1236,6 +1315,11 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $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 * Revision 1.126 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -137,7 +137,9 @@ extern void synth(Design*des);
extern void synth2(Design*des); extern void synth2(Design*des);
extern void syn_rules(Design*des); extern void syn_rules(Design*des);
extern void nodangle(Design*des); extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des); extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*); typedef void (*net_func)(Design*);
static struct net_func_map { static struct net_func_map {
@ -149,7 +151,9 @@ static struct net_func_map {
{ "synth", &synth }, { "synth", &synth },
{ "synth2", &synth2 }, { "synth2", &synth2 },
{ "syn-rules", &syn_rules }, { "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio }, { "xnfio", &xnfio },
#endif
{ 0, 0 } { 0, 0 }
}; };
@ -744,6 +748,11 @@ int main(int argc, char*argv[])
/* /*
* $Log: main.cc,v $ * $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 * Revision 1.86 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -42,7 +42,7 @@ NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), var_(0), bmux_(0) : sig_(s), mem_(0), var_(0), bmux_(0)
{ {
loff_ = 0; loff_ = 0;
lwid_ = sig_->pin_count(); lwid_ = sig_->vector_width();
sig_->incr_lref(); sig_->incr_lref();
more = 0; more = 0;
} }
@ -130,7 +130,7 @@ void NetAssign_::set_part(unsigned lo, unsigned lw)
loff_ = lo; loff_ = lo;
lwid_ = lw; lwid_ = lw;
if (sig_) { if (sig_) {
assert(sig_->pin_count() >= (lo + lw)); assert(sig_->vector_width() >= (lo + lw));
} else { } else {
assert(mem_); assert(mem_);
assert(lwid_ == mem_->width()); 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 $ * $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 * Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing. * 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 * Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to * Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -33,110 +33,14 @@
# include "netlist.h" # include "netlist.h"
# include <assert.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 $ * $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 * Revision 1.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -227,14 +227,12 @@ NetNode::~NetNode()
} }
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) 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), type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
local_flag_(false), eref_count_(0), lref_count_(0) local_flag_(false), eref_count_(0), lref_count_(0)
{ {
assert(s); assert(s);
release_list_ = 0;
verinum::V init_value = verinum::Vz; verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE; Link::DIR dir = Link::PASSIVE;
@ -257,25 +255,21 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
break; break;
} }
for (unsigned idx = 0 ; idx < npins ; idx += 1) { pin(0).set_name(perm_string::literal("P"), 0);
pin(idx).set_name(perm_string::literal("P"), idx); pin(0).set_dir(dir);
pin(idx).set_dir(dir); pin(0).set_init(init_value);
pin(idx).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) 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), sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls), port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls),
local_flag_(false), eref_count_(0), lref_count_(0) local_flag_(false), eref_count_(0), lref_count_(0)
{ {
assert(s); assert(s);
release_list_ = 0;
verinum::V init_value = verinum::Vz; verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE; Link::DIR dir = Link::PASSIVE;
@ -297,11 +291,9 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
break; break;
} }
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { pin(0).set_name(perm_string::literal("P"), 0);
pin(idx).set_name(perm_string::literal("P"), idx); pin(0).set_dir(dir);
pin(idx).set_dir(dir); pin(0).set_init(init_value);
pin(idx).set_init(init_value);
}
s->add_signal(this); s->add_signal(this);
} }
@ -325,14 +317,6 @@ NetNet::~NetNet()
if (scope()) if (scope())
scope()->rem_signal(this); 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 NetNet::Type NetNet::type() const
@ -409,6 +393,14 @@ long NetNet::msb() const
return msb_; 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 bool NetNet::sb_is_valid(long sb) const
{ {
if (msb_ >= lsb_) if (msb_ >= lsb_)
@ -464,7 +456,7 @@ unsigned NetNet::get_refs() const
NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid) 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) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(sig->pin(idx+off), pin(idx)); connect(sig->pin(idx+off), pin(idx));
@ -474,6 +466,33 @@ NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
set_line(*sig); 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() NetProc::NetProc()
: next_(0) : next_(0)
{ {
@ -694,33 +713,31 @@ const verinum& NetFF::sset_value() const
* 3 -- Cin * 3 -- Cin
* 4 -- Cout * 4 -- Cout
* 5 -- Overflow * 5 -- Overflow
* 6 -- DataA[0] * 6 -- DataA (normally a vector)
* 7 -- DataB[0] * 7 -- DataB (normally a vector)
* 8 -- Result[0] * 8 -- Result (normally a vector)
*/ */
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w) 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( pin(0).set_dir(Link::INPUT);
perm_string::literal("Add_Sub"), 0); pin(0).set_name(perm_string::literal("Add_Sub"), 0);
pin(1).set_dir(Link::INPUT); pin(1).set_name( pin(1).set_dir(Link::INPUT);
perm_string::literal("Aclr"), 0); pin(1).set_name(perm_string::literal("Aclr"), 0);
pin(2).set_dir(Link::INPUT); pin(2).set_name( pin(2).set_dir(Link::INPUT);
perm_string::literal("Clock"), 0); pin(2).set_name(perm_string::literal("Clock"), 0);
pin(3).set_dir(Link::INPUT); pin(3).set_name( pin(3).set_dir(Link::INPUT);
perm_string::literal("Cin"), 0); pin(3).set_name(perm_string::literal("Cin"), 0);
pin(4).set_dir(Link::OUTPUT); pin(4).set_name( pin(4).set_dir(Link::OUTPUT);
perm_string::literal("Cout"), 0); pin(4).set_name(perm_string::literal("Cout"), 0);
pin(5).set_dir(Link::OUTPUT); pin(5).set_name( pin(5).set_dir(Link::OUTPUT);
perm_string::literal("Overflow"), 0); pin(5).set_name(perm_string::literal("Overflow"), 0);
for (unsigned idx = 0 ; idx < w ; idx += 1) { pin(6).set_dir(Link::INPUT);
pin_DataA(idx).set_dir(Link::INPUT); pin(6).set_name(perm_string::literal("DataA"), 0);
pin_DataB(idx).set_dir(Link::INPUT); pin(7).set_dir(Link::INPUT);
pin_Result(idx).set_dir(Link::OUTPUT); pin(7).set_name(perm_string::literal("DataB"), 0);
pin_DataA(idx).set_name(perm_string::literal("DataA"), idx); pin(8).set_dir(Link::OUTPUT);
pin_DataB(idx).set_name(perm_string::literal("DataB"), idx); pin(8).set_name(perm_string::literal("Result"), 0);
pin_Result(idx).set_name(perm_string::literal("Result"), idx);
}
} }
NetAddSub::~NetAddSub() NetAddSub::~NetAddSub()
@ -729,7 +746,7 @@ NetAddSub::~NetAddSub()
unsigned NetAddSub::width()const unsigned NetAddSub::width()const
{ {
return (pin_count() - 6) / 3; return width_;
} }
Link& NetAddSub::pin_Cout() Link& NetAddSub::pin_Cout()
@ -742,46 +759,34 @@ const Link& NetAddSub::pin_Cout() const
return pin(4); return pin(4);
} }
Link& NetAddSub::pin_DataA(unsigned idx) Link& NetAddSub::pin_DataA()
{ {
idx = 6 + idx*3; return pin(6);
assert(idx < pin_count());
return pin(idx);
} }
const Link& NetAddSub::pin_DataA(unsigned idx) const const Link& NetAddSub::pin_DataA() const
{ {
idx = 6 + idx*3; return pin(6);
assert(idx < pin_count());
return pin(idx);
} }
Link& NetAddSub::pin_DataB(unsigned idx) Link& NetAddSub::pin_DataB()
{ {
idx = 7 + idx*3; return pin(7);
assert(idx < pin_count());
return pin(idx);
} }
const Link& NetAddSub::pin_DataB(unsigned idx) const const Link& NetAddSub::pin_DataB() const
{ {
idx = 7 + idx*3; return pin(7);
assert(idx < pin_count());
return pin(idx);
} }
Link& NetAddSub::pin_Result(unsigned idx) Link& NetAddSub::pin_Result()
{ {
idx = 8 + idx*3; return pin(8);
assert(idx < pin_count());
return pin(idx);
} }
const Link& NetAddSub::pin_Result(unsigned idx) const const Link& NetAddSub::pin_Result() const
{ {
idx = 8 + idx*3; return pin(8);
assert(idx < pin_count());
return pin(idx);
} }
/* /*
@ -1591,8 +1596,8 @@ const Link& NetRamDq::pin_Q(unsigned idx) const
return pin(3+awidth_+width()+idx); return pin(3+awidth_+width()+idx);
} }
NetBUFZ::NetBUFZ(NetScope*s, perm_string n) NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2) : NetNode(s, n, 2), width_(w)
{ {
pin(0).set_dir(Link::OUTPUT); pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT); 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) NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n)
: NetNode(s, n, 3) : NetNode(s, n, 3)
@ -1656,7 +1665,7 @@ NetProc* NetCondit::else_clause()
} }
NetConst::NetConst(NetScope*s, perm_string n, verinum::V v) 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_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0); 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) 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()]; pin(0).set_dir(Link::OUTPUT);
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { pin(0).set_name(perm_string::literal("O"), 0);
pin(idx).set_dir(Link::OUTPUT); value_ = new verinum::V[width_];
pin(idx).set_name(perm_string::literal("O"), idx); for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
value_[idx] = val.get(idx); value_[idx] = val.get(idx);
} }
} }
@ -1682,10 +1691,15 @@ NetConst::~NetConst()
verinum::V NetConst::value(unsigned idx) const verinum::V NetConst::value(unsigned idx) const
{ {
assert(idx < pin_count()); assert(idx < width_);
return value_[idx]; return value_[idx];
} }
unsigned NetConst::width() const
{
return width_;
}
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po) NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
: scope_(s), statement_(0), result_sig_(result), result_var_(0), ports_(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) 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(); net_->incr_eref();
set_line(*n); set_line(*n);
cast_signed(net_->get_signed()); cast_signed(net_->get_signed());
} }
#if 0
NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l) NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
: NetExpr(m - l + 1), net_(n) : NetExpr(m - l + 1), net_(n)
{ {
@ -2090,6 +2103,7 @@ NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
set_line(*n); set_line(*n);
cast_signed(net_->get_signed()); cast_signed(net_->get_signed());
} }
#endif
NetESignal::~NetESignal() NetESignal::~NetESignal()
{ {
@ -2103,13 +2117,13 @@ perm_string NetESignal::name() const
unsigned NetESignal::bit_count() const unsigned NetESignal::bit_count() const
{ {
return msi_ - lsi_ + 1; return net_->vector_width();
} }
Link& NetESignal::bit(unsigned idx) Link& NetESignal::bit(unsigned idx)
{ {
assert(idx <= (msi_ - lsi_)); assert(idx <= 0);
return net_->pin(idx + lsi_); return net_->pin(idx);
} }
const NetNet* NetESignal::sig() const const NetNet* NetESignal::sig() const
@ -2119,12 +2133,12 @@ const NetNet* NetESignal::sig() const
unsigned NetESignal::lsi() const unsigned NetESignal::lsi() const
{ {
return lsi_; return net_->lsb();
} }
unsigned NetESignal::msi() const unsigned NetESignal::msi() const
{ {
return msi_; return net_->msb();
} }
NetEBitSel::NetEBitSel(NetESignal*sig, NetExpr*ex) NetEBitSel::NetEBitSel(NetESignal*sig, NetExpr*ex)
@ -2231,8 +2245,9 @@ NetEUReduce::~NetEUReduce()
{ {
} }
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t) NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
: NetNode(s, n, pins), type_(t) TYPE t, unsigned wid)
: NetNode(s, n, pins), type_(t), width_(wid)
{ {
pin(0).set_dir(Link::OUTPUT); pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0); 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) NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
: name_(n), proc_(0), ports_(po) : name_(n), proc_(0), ports_(po)
{ {
@ -2281,6 +2306,11 @@ const NetProc*NetTaskDef::proc() const
/* /*
* $Log: netlist.cc,v $ * $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 * Revision 1.226 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
/* /*
@ -345,8 +345,11 @@ class NetNode : public NetObj {
/* /*
* NetNet is a special kind of NetObj that doesn't really do anything, * NetNet is a special kind of NetObj that doesn't really do anything,
* but carries the properties of the wire/reg/trireg, including its * 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 * name. Scalers and vectors are all the same thing here, a NetNet
* NetNet. NetNet objects also appear as side effects of synthesis or * 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. * other abstractions.
* *
* Note that INTEGER types are an alias for a ``reg signed [31:0]''. * 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. * 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 * anything and they are not a data sink, per se. The pins follow the
* values on the nexus. * values on the nexus.
*/ */
@ -397,6 +400,7 @@ class NetNet : public NetObj {
reg [1:8] has 8 bits, msb==1 and lsb==8. */ reg [1:8] has 8 bits, msb==1 and lsb==8. */
long msb() const; long msb() const;
long lsb() const; long lsb() const;
long vector_width() const;
/* This method converts a signed index (the type that might be /* This method converts a signed index (the type that might be
found in the verilog source) to a pin number. It accounts found in the verilog source) to a pin number. It accounts
@ -431,12 +435,6 @@ class NetNet : public NetObj {
friend class NetScope; friend class NetScope;
NetNet*sig_next_, *sig_prev_; 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: private:
Type type_; Type type_;
PortType port_type_; PortType port_type_;
@ -472,18 +470,21 @@ class NetAddSub : public NetNode {
Link& pin_Cout(); Link& pin_Cout();
Link& pin_Overflow(); Link& pin_Overflow();
Link& pin_DataA(unsigned idx); Link& pin_DataA();
Link& pin_DataB(unsigned idx); Link& pin_DataB();
Link& pin_Result(unsigned idx); Link& pin_Result();
const Link& pin_Cout() const; const Link& pin_Cout() const;
const Link& pin_DataA(unsigned idx) const; const Link& pin_DataA() const;
const Link& pin_DataB(unsigned idx) const; const Link& pin_DataB() const;
const Link& pin_Result(unsigned idx) const; const Link& pin_Result() const;
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const; virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun); virtual void functor_node(Design*des, functor_t*fun);
private:
unsigned width_;
}; };
/* /*
@ -1122,7 +1123,7 @@ class NetECRealParam : public NetECReal {
perm_string name_; perm_string name_;
}; };
/* /* DEPRECATED -- REMOVE ME! Use NetPartSelect instead.
* This is a special, magical NetNet object. It represents a constant * This is a special, magical NetNet object. It represents a constant
* bit or part select of another NetNet, so is used to return that * bit or part select of another NetNet, so is used to return that
* selection from elaborate function. None of these should remain once * 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; 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 * The NetBUFZ is a magic device that represents the continuous
* assign, with the output being the target register and the input * assign, with the output being the target register and the input
@ -1145,11 +1169,16 @@ class NetSubnet : public NetNet {
class NetBUFZ : public NetNode { class NetBUFZ : public NetNode {
public: public:
explicit NetBUFZ(NetScope*s, perm_string n); explicit NetBUFZ(NetScope*s, perm_string n, unsigned wid);
~NetBUFZ(); ~NetBUFZ();
unsigned width() const;
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const; virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
}; };
/* /*
@ -1189,12 +1218,14 @@ class NetConst : public NetNode {
~NetConst(); ~NetConst();
verinum::V value(unsigned idx) const; verinum::V value(unsigned idx) const;
unsigned width() const;
virtual bool emit_node(struct target_t*) const; virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*, functor_t*); virtual void functor_node(Design*, functor_t*);
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
private: private:
unsigned width_;
verinum::V*value_; verinum::V*value_;
}; };
@ -1219,16 +1250,19 @@ class NetLogic : public NetNode {
NOTIF0, NOTIF1, OR, PULLDOWN, PULLUP, RNMOS, RPMOS, NOTIF0, NOTIF1, OR, PULLDOWN, PULLUP, RNMOS, RPMOS,
PMOS, XNOR, XOR }; 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 void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const; virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*, functor_t*); virtual void functor_node(Design*, functor_t*);
private: 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 * 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 * l-val reg when it is executed. The code generator is expected to
* know what that means. All the expressions are structural and behave * know what that means.
* 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.
*/ */
class NetCAssign : public NetProc, public NetNode { class NetCAssign : public NetAssignBase {
public: public:
explicit NetCAssign(NetScope*s, perm_string n, NetNet*l); explicit NetCAssign(NetAssign_*lv, NetExpr*rv);
~NetCAssign(); ~NetCAssign();
const Link& lval_pin(unsigned) const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input();
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) 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 private: // not implemented
NetCAssign(const NetCAssign&); NetCAssign(const NetCAssign&);
@ -1709,20 +1729,15 @@ class NetCondit : public NetProc {
* lval is the expression of the "deassign <expr>;" statement with the * lval is the expression of the "deassign <expr>;" statement with the
* expr elaborated to a net. * expr elaborated to a net.
*/ */
class NetDeassign : public NetProc { class NetDeassign : public NetAssignBase {
public: public:
explicit NetDeassign(NetNet*l); explicit NetDeassign(NetAssign_*l);
~NetDeassign(); ~NetDeassign();
const NetNet*lval() const;
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private:
NetNet*lval_;
private: // not implemented private: // not implemented
NetDeassign(const NetDeassign&); NetDeassign(const NetDeassign&);
NetDeassign& operator= (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 * 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 * l-val net when it is executed. The code generator is expected to
* know what that means. All the expressions are structural and behave * know what that means.
* 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.
*/ */
class NetForce : public NetProc, public NetNode { class NetForce : public NetAssignBase {
public: public:
explicit NetForce(NetScope*s, perm_string n, NetNet*l); explicit NetForce(NetAssign_*l, NetExpr*r);
~NetForce(); ~NetForce();
const Link& lval_pin(unsigned) const;
const NetNet*lval() const;
virtual NexusSet* nex_input(); virtual NexusSet* nex_input();
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) 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 * lval is the expression of the "release <expr>;" statement with the
* expr elaborated to a net. * expr elaborated to a net.
*/ */
class NetRelease : public NetProc { class NetRelease : public NetAssignBase {
public: public:
explicit NetRelease(NetNet*l); explicit NetRelease(NetAssign_*l);
~NetRelease(); ~NetRelease();
const NetNet*lval() const;
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private: 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: public:
NetESignal(NetNet*n); NetESignal(NetNet*n);
NetESignal(NetNet*n, unsigned msi, unsigned lsi);
~NetESignal(); ~NetESignal();
perm_string name() const; perm_string name() const;
@ -2978,8 +2972,6 @@ class NetESignal : public NetExpr {
private: private:
NetNet*net_; NetNet*net_;
unsigned msi_;
unsigned lsi_;
}; };
/* /*
@ -3357,6 +3349,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $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 * Revision 1.321 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -30,7 +30,7 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
{ {
if (val == 0) if (val == 0)
return sig; return sig;
#if 0
NetScope*scope = sig->scope(); NetScope*scope = sig->scope();
unsigned long abs_val = (val >= 0)? val : (-val); unsigned long abs_val = (val >= 0)? val : (-val);
unsigned width = sig->pin_count(); unsigned width = sig->pin_count();
@ -70,6 +70,10 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
des->add_node(val_c); des->add_node(val_c);
return res; 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 $ * $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 * Revision 1.8 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -952,7 +952,7 @@ void pform_make_modgates(perm_string type,
delete gates; delete gates;
} }
PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval, static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
svector<PExpr*>*del, svector<PExpr*>*del,
struct str_pair_t str) struct str_pair_t str)
{ {
@ -1597,6 +1597,11 @@ int pform_parse(const char*path, FILE*file)
/* /*
* $Log: pform.cc,v $ * $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 * Revision 1.129 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "netlist.h" # include "netlist.h"
@ -270,9 +270,6 @@ extern void pform_make_modgates(perm_string type,
svector<lgate>*gates); svector<lgate>*gates);
/* Make a continuous assignment node, with optional bit- or part- select. */ /* 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, extern void pform_make_pgassign_list(svector<PExpr*>*alist,
svector<PExpr*>*del, svector<PExpr*>*del,
struct str_pair_t str, struct str_pair_t str,
@ -298,6 +295,11 @@ extern void pform_dump(ostream&out, Module*mod);
/* /*
* $Log: pform.h,v $ * $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 * Revision 1.81 2004/08/26 04:02:04 steve
* Add support for localparam ranges. * Add support for localparam ranges.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -768,7 +768,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
if (ff->pin_Enable().is_linked()) { if (ff->pin_Enable().is_linked()) {
NetLogic*ce_and = new NetLogic(scope, NetLogic*ce_and = new NetLogic(scope,
scope->local_symbol(), 3, scope->local_symbol(), 3,
NetLogic::AND); NetLogic::AND, 1);
des->add_node(ce_and); des->add_node(ce_and);
connect(ff->pin_Enable(), ce_and->pin(1)); connect(ff->pin_Enable(), ce_and->pin(1));
connect(ce->pin(0), ce_and->pin(2)); connect(ce->pin(0), ce_and->pin(2));
@ -985,6 +985,11 @@ void synth2(Design*des)
/* /*
* $Log: synth2.cc,v $ * $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 * Revision 1.39 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -129,20 +129,10 @@ extern "C" const char*ivl_const_bits(ivl_net_const_t net)
return net->b.bits_; 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(net);
assert(idx < net->width_); return net->pin_;
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_;
} }
extern "C" int ivl_const_signed(ivl_net_const_t net) 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_; 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) extern "C" const char* ivl_event_name(ivl_event_t net)
{ {
static char*name_buffer = 0; 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]; 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) 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) extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
{ {
assert(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_MOD:
case IVL_LPM_MULT: case IVL_LPM_MULT:
case IVL_LPM_SUB: case IVL_LPM_SUB:
assert(idx < net->u_.arith.width); assert(idx == 0);
return net->u_.arith.a[idx]; return net->u_.arith.a;
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
@ -765,6 +778,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
else else
return net->u_.ff.d.pins[idx]; return net->u_.ff.d.pins[idx];
case IVL_LPM_PART:
assert(idx == 0);
return net->u_.part.a;
default: default:
assert(0); assert(0);
return 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_MOD:
case IVL_LPM_MULT: case IVL_LPM_MULT:
case IVL_LPM_SUB: case IVL_LPM_SUB:
assert(idx < net->u_.arith.width); assert(idx == 0);
return net->u_.arith.b[idx]; return net->u_.arith.b;
default: default:
assert(0); 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_MOD:
case IVL_LPM_MULT: case IVL_LPM_MULT:
case IVL_LPM_SUB: case IVL_LPM_SUB:
assert(idx < net->u_.arith.width); assert(idx == 0);
return net->u_.arith.q[idx]; return net->u_.arith.q;
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NE:
assert(idx == 0); assert(idx == 0);
return net->u_.arith.q[0]; return net->u_.arith.q;
case IVL_LPM_FF: case IVL_LPM_FF:
case IVL_LPM_RAM: 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]); assert(idx < net->u_.ufunc.port_wid[0]);
return net->u_.ufunc.pins[idx]; return net->u_.ufunc.pins[idx];
case IVL_LPM_PART:
assert(idx == 0);
return net->u_.part.q;
default: default:
assert(0); assert(0);
return 0; return 0;
@ -987,6 +1008,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return 0; return 0;
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
return 0; return 0;
case IVL_LPM_PART:
return net->u_.part.signed_flag;
default: default:
assert(0); assert(0);
return 0; return 0;
@ -1035,6 +1058,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
return net->u_.shift.width; return net->u_.shift.width;
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
return net->u_.ufunc.port_wid[0]; return net->u_.ufunc.port_wid[0];
case IVL_LPM_PART:
return net->u_.part.width;
default: default:
assert(0); assert(0);
return 0; return 0;
@ -1091,12 +1116,20 @@ extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
return net->loff_; 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); assert(net);
return net->width_; 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) extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
{ {
assert(net); 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); assert(net->type_ != IVL_LVAL_MEM);
return ivl_signal_pin(net->n.sig, idx+net->loff_); return ivl_signal_pin(net->n.sig, idx+net->loff_);
} }
#endif
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net) 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; 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); return net->pin_;
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_;
} }
extern "C" int ivl_signal_msb(ivl_signal_t net) 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; 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) extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
{ {
return net->port_; return net->port_;
@ -1760,15 +1787,12 @@ extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx)
switch (net->type_) { switch (net->type_) {
case IVL_ST_ASSIGN: case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB: case IVL_ST_ASSIGN_NB:
assert(idx < net->u_.assign_.lvals_);
return net->u_.assign_.lval_ + idx;
case IVL_ST_CASSIGN: case IVL_ST_CASSIGN:
case IVL_ST_DEASSIGN: case IVL_ST_DEASSIGN:
case IVL_ST_FORCE: case IVL_ST_FORCE:
case IVL_ST_RELEASE: case IVL_ST_RELEASE:
assert(idx < net->u_.cassign_.lvals); assert(idx < net->u_.assign_.lvals_);
return net->u_.cassign_.lval + idx; return net->u_.assign_.lval_ + idx;
default: default:
assert(0); assert(0);
@ -1781,13 +1805,11 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
switch (net->type_) { switch (net->type_) {
case IVL_ST_ASSIGN: case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB: case IVL_ST_ASSIGN_NB:
return net->u_.assign_.lvals_;
case IVL_ST_CASSIGN: case IVL_ST_CASSIGN:
case IVL_ST_DEASSIGN: case IVL_ST_DEASSIGN:
case IVL_ST_FORCE: case IVL_ST_FORCE:
case IVL_ST_RELEASE: case IVL_ST_RELEASE:
return net->u_.cassign_.lvals; return net->u_.assign_.lvals_;
default: default:
assert(0); 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) extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
{ {
assert((net->type_ == IVL_ST_ASSIGN) 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; 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_) { switch(cur->type_) {
case IVL_LVAL_MUX: case IVL_LVAL_MUX:
sum += 1; sum += 1;
break; break;
case IVL_LVAL_REG: case IVL_LVAL_REG:
sum += ivl_lval_pins(cur); sum += ivl_lval_width(cur);
break; break;
case IVL_LVAL_MEM: case IVL_LVAL_MEM:
sum += ivl_memory_width(ivl_lval_mem(cur)); 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; 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) extern "C" ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx)
{ {
switch (net->type_) { switch (net->type_) {
@ -1892,6 +1895,7 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net)
switch (net->type_) { switch (net->type_) {
case IVL_ST_ASSIGN: case IVL_ST_ASSIGN:
case IVL_ST_ASSIGN_NB: case IVL_ST_ASSIGN_NB:
case IVL_ST_CASSIGN:
return net->u_.assign_.rval_; return net->u_.assign_.rval_;
default: default:
assert(0); 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 $ * $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 * Revision 1.108 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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_);
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(); 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_.lvals_ = cnt;
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt]; stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
stmt_cur_->u_.assign_.delay = 0; 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); assert(expr_ == 0);
net->rval()->expr_scan(this); net->rval()->expr_scan(this);
stmt_cur_->u_.assign_.rval_ = expr_; 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_->type_ = IVL_ST_CASSIGN;
stmt_cur_->u_.cassign_.lvals = 1; /* Make the l-value fields. */
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*) make_assign_lvals_(net);
calloc(1, sizeof(struct ivl_lval_s));
const NetNet*lsig = net->lval(); assert(expr_ == 0);
net->rval()->expr_scan(this);
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count(); stmt_cur_->u_.assign_.rval_ = expr_;
stmt_cur_->u_.cassign_.lval[0].loff_ = 0; expr_ = 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]);
}
return true; return true;
} }
@ -485,19 +438,9 @@ bool dll_target::proc_deassign(const NetDeassign*net)
assert(stmt_cur_->type_ == IVL_ST_NONE); assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_DEASSIGN; 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(); /* Make the l-value fields. */
make_assign_lvals_(net);
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;
return true; return true;
} }
@ -554,52 +497,19 @@ bool dll_target::proc_disable(const NetDisable*net)
bool dll_target::proc_force(const NetForce*net) bool dll_target::proc_force(const NetForce*net)
{ {
assert(stmt_cur_); assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE); assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_FORCE; stmt_cur_->type_ = IVL_ST_FORCE;
stmt_cur_->u_.cassign_.lvals = 1; /* Make the l-value fields. */
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*) make_assign_lvals_(net);
calloc(1, sizeof(struct ivl_lval_s));
const NetNet*lsig = net->lval(); assert(expr_ == 0);
assert(lsig); net->rval()->expr_scan(this);
ivl_signal_t sig = find_signal(des_, lsig); stmt_cur_->u_.assign_.rval_ = expr_;
assert(sig); expr_ = 0;
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]);
}
return true; return true;
} }
@ -630,47 +540,8 @@ bool dll_target::proc_release(const NetRelease*net)
stmt_cur_->type_ = IVL_ST_RELEASE; stmt_cur_->type_ = IVL_ST_RELEASE;
/* If there is no signal attached to the release, then it is /* Make the l-value fields. */
the victim of an elided net. In that case, simply state make_assign_lvals_(net);
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;
return true; return true;
} }
@ -872,6 +743,11 @@ void dll_target::proc_while(const NetWhile*net)
/* /*
* $Log: t-dll-proc.cc,v $ * $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 * Revision 1.65 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -650,8 +650,8 @@ bool dll_target::bufz(const NetBUFZ*net)
assert(net->pin_count() == 2); assert(net->pin_count() == 2);
obj->type_ = IVL_LO_BUFZ; obj->type_ = IVL_LO_BUFZ;
obj->width_= net->width();
obj->npins_ = 2; obj->npins_= 2;
obj->pins_ = new ivl_nexus_t[2]; obj->pins_ = new ivl_nexus_t[2];
/* Get the ivl_nexus_t objects connected to the two pins. /* 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; struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
obj->width_ = net->width();
switch (net->type()) { switch (net->type()) {
case NetLogic::AND: case NetLogic::AND:
obj->type_ = IVL_LO_AND; obj->type_ = IVL_LO_AND;
@ -943,16 +945,6 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
scope_add_logic(scope, obj); 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 * An IVL_LPM_UFUNC represents a node in a combinational expression
* that calls a user defined function. I create an LPM object that has * 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.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(); nex = net->pin_Result().nexus();
assert(nex->t_cookie()); assert(nex->t_cookie());
obj->u_.arith.q[idx] = (ivl_nexus_t) nex->t_cookie(); obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q[idx], obj, 0, nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
IVL_DR_STRONG, IVL_DR_STRONG);
nex = net->pin_DataA(idx).nexus(); nex = net->pin_DataA().nexus();
assert(nex->t_cookie()); assert(nex->t_cookie());
obj->u_.arith.a[idx] = (ivl_nexus_t) nex->t_cookie(); obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0, nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
IVL_DR_HiZ, IVL_DR_HiZ);
nex = net->pin_DataB(idx).nexus(); nex = net->pin_DataB().nexus();
assert(nex->t_cookie()); assert(nex->t_cookie());
obj->u_.arith.b[idx] = (ivl_nexus_t) nex->t_cookie(); obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.b[idx], obj, 0, nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
IVL_DR_HiZ, IVL_DR_HiZ);
}
/* If the carry output is connected, then connect the extra Q /* If the carry output is connected, then connect the extra Q
pin to the carry nexus and zero the a and b inputs. */ pin to the carry nexus and zero the a and b inputs. */
if (net->pin_Cout().is_linked()) { if (net->pin_Cout().is_linked()) {
#if 0
unsigned carry = obj->u_.arith.width - 1; unsigned carry = obj->u_.arith.width - 1;
const Nexus*nex = net->pin_Cout().nexus(); const Nexus*nex = net->pin_Cout().nexus();
assert(nex->t_cookie()); 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.a[carry] = 0;
obj->u_.arith.b[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); 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.width = net->width();
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0; 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.q = new ivl_nexus_t[1 + 2 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + 1; obj->u_.arith.a = obj->u_.arith.q + 1;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width; 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, nexus_lpm_add(obj->u_.arith.b[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ); 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); 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.width = wid;
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0; 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.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.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + 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; 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); scope_add_lpm(obj->scope, obj);
} }
@ -1438,7 +1430,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
wid = net->width_b(); wid = net->width_b();
obj->u_.arith.width = wid; obj->u_.arith.width = wid;
#if 0
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width]; 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.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + 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; 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); scope_add_lpm(obj->scope, obj);
} }
@ -1732,6 +1726,7 @@ void dll_target::lpm_mult(const NetMult*net)
obj->u_.arith.width = wid; obj->u_.arith.width = wid;
#if 0
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width]; 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.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + 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; 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); 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 * The assignment l-values are captured by the assignment statements
* themselves in the process handling. * 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; 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*)) { if (obj->width_ <= sizeof(char*)) {
bits = obj->b.bit_; 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 /* Connect to all the nexus objects. Note that the one-bit
case can be handled more efficiently without allocating case can be handled more efficiently without allocating
array space. */ 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 { ivl_drive_t drv0, drv1;
obj->n.pins_ = new ivl_nexus_t[obj->width_]; drive_from_link(net->pin(0), drv0, drv1);
for (unsigned idx = 0 ; idx < obj->width_ ; idx += 1) { const Nexus*nex = net->pin(0).nexus();
if (! net->pin(idx).is_linked()) assert(nex->t_cookie());
continue; 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_.nconsts += 1;
des_.consts = (ivl_net_const_t*) 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 /* Save the primitive properties of the signal in the
ivl_signal_t object. */ ivl_signal_t object. */
obj->width_ = net->pin_count(); obj->width_ = net->vector_width();
obj->signed_= net->get_signed()? 1 : 0; obj->signed_= net->get_signed()? 1 : 0;
obj->lsb_index = net->lsb(); obj->lsb_index = net->lsb();
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1; 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 t_cookie of the Nexus object so that I find it again when I
next encounter the nexus. */ next encounter the nexus. */
if (obj->width_ == 1) { const Nexus*nex = net->pin(0).nexus();
const Nexus*nex = net->pin(0).nexus(); if (nex->t_cookie()) {
if (nex->t_cookie()) { obj->pin_ = (ivl_nexus_t)nex->t_cookie();
obj->n.pin_ = (ivl_nexus_t)nex->t_cookie(); nexus_sig_add(obj->pin_, obj, 0);
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;
}
} else { } else {
unsigned idx; ivl_nexus_t tmp = nexus_sig_make(obj, 0);
tmp->name_ = strings_.add(nex->name());
obj->n.pins_ = (ivl_nexus_t*) nex->t_cookie(tmp);
calloc(obj->width_, sizeof(ivl_nexus_t)); obj->pin_ = tmp;
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;
}
}
} }
} }
extern const struct target tgt_dll = { "dll", &dll_target_obj }; 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 $ * $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 * Revision 1.131 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "target.h" # include "target.h"
@ -82,9 +82,8 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_mult(const NetMult*); void lpm_mult(const NetMult*);
void lpm_mux(const NetMux*); void lpm_mux(const NetMux*);
void lpm_ram_dq(const NetRamDq*); void lpm_ram_dq(const NetRamDq*);
bool part_select(const NetPartSelect*);
void net_assign(const NetAssign_*); void net_assign(const NetAssign_*);
bool net_cassign(const NetCAssign*);
bool net_force(const NetForce*);
bool net_function(const NetUserFunc*); bool net_function(const NetUserFunc*);
bool net_const(const NetConst*); bool net_const(const NetConst*);
void net_probe(const NetEvProbe*); 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 add_root(ivl_design_s &des_, const NetScope *s);
void make_assign_lvals_(const NetAssignBase*net);
void sub_off_from_expr_(long); void sub_off_from_expr_(long);
void mul_expr_by_const_(long); void mul_expr_by_const_(long);
@ -344,9 +344,16 @@ struct ivl_lpm_s {
struct ivl_lpm_arith_s { struct ivl_lpm_arith_s {
unsigned width; unsigned width;
unsigned signed_flag :1; unsigned signed_flag :1;
ivl_nexus_t*q, *a, *b; ivl_nexus_t q, a, b;
} arith; } arith;
struct ivl_part_s {
unsigned width;
unsigned base;
unsigned signed_flag :1;
ivl_nexus_t q, a;
} part;
struct ivl_lpm_ufunc_s { struct ivl_lpm_ufunc_s {
ivl_scope_t def; ivl_scope_t def;
unsigned ports; unsigned ports;
@ -395,10 +402,7 @@ struct ivl_net_const_s {
char *bits_; char *bits_;
} b; } b;
union { ivl_nexus_t pin_;
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
}; };
/* /*
@ -407,6 +411,7 @@ struct ivl_net_const_s {
*/ */
struct ivl_net_logic_s { struct ivl_net_logic_s {
ivl_logic_t type_; ivl_logic_t type_;
unsigned width_;
ivl_udp_t udp; ivl_udp_t udp;
perm_string name_; perm_string name_;
@ -578,10 +583,7 @@ struct ivl_signal_s {
perm_string name_; perm_string name_;
ivl_scope_t scope_; ivl_scope_t scope_;
union { ivl_nexus_t pin_;
ivl_nexus_t pin_;
ivl_nexus_t*pins_;
} n;
struct ivl_attribute_s*attr; struct ivl_attribute_s*attr;
unsigned nattr; unsigned nattr;
@ -595,7 +597,8 @@ struct ivl_signal_s {
struct ivl_statement_s { struct ivl_statement_s {
enum ivl_statement_type_e type_; enum ivl_statement_type_e type_;
union { 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_; unsigned lvals_;
struct ivl_lval_s*lval_; struct ivl_lval_s*lval_;
ivl_expr_t rval_; ivl_expr_t rval_;
@ -615,13 +618,6 @@ struct ivl_statement_s {
struct ivl_statement_s*case_st; struct ivl_statement_s*case_st;
} case_; } 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 */ struct { /* IVL_ST_CONDIT */
/* This is the condition expression */ /* This is the condition expression */
ivl_expr_t cond_; ivl_expr_t cond_;
@ -684,6 +680,11 @@ struct ivl_variable_s {
/* /*
* $Log: t-dll.h,v $ * $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 * Revision 1.115 2004/10/04 01:10:56 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -137,20 +137,19 @@ void target_t::lpm_ram_dq(const NetRamDq*)
"Unhandled NetRamDq." << endl; "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*) void target_t::net_case_cmp(const NetCaseCmp*)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
"Unhandled case compare node." << endl; "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*) bool target_t::net_const(const NetConst*)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
@ -158,13 +157,6 @@ bool target_t::net_const(const NetConst*)
return false; 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) bool target_t::net_function(const NetUserFunc*net)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
@ -420,6 +412,11 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/* /*
* $Log: target.cc,v $ * $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 * Revision 1.69 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "netlist.h" # include "netlist.h"
@ -86,14 +86,14 @@ struct target_t {
virtual void lpm_mux(const NetMux*); virtual void lpm_mux(const NetMux*);
virtual void lpm_ram_dq(const NetRamDq*); virtual void lpm_ram_dq(const NetRamDq*);
virtual bool part_select(const NetPartSelect*);
/* Output a gate (called for each gate) */ /* Output a gate (called for each gate) */
virtual void logic(const NetLogic*); virtual void logic(const NetLogic*);
virtual bool bufz(const NetBUFZ*); virtual bool bufz(const NetBUFZ*);
virtual void udp(const NetUDP*); virtual void udp(const NetUDP*);
virtual void net_case_cmp(const NetCaseCmp*); virtual void net_case_cmp(const NetCaseCmp*);
virtual bool net_cassign(const NetCAssign*);
virtual bool net_const(const NetConst*); virtual bool net_const(const NetConst*);
virtual bool net_force(const NetForce*);
virtual bool net_function(const NetUserFunc*); virtual bool net_function(const NetUserFunc*);
virtual void net_probe(const NetEvProbe*); virtual void net_probe(const NetEvProbe*);
@ -170,6 +170,11 @@ extern const struct target *target_table[];
/* /*
* $Log: target.h,v $ * $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 * Revision 1.65 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -25,17 +25,25 @@
# include "target.h" # include "target.h"
extern const struct target tgt_dll; extern const struct target tgt_dll;
#ifdef WITH_T_XNF
extern const struct target tgt_xnf; extern const struct target tgt_xnf;
#endif
const struct target *target_table[] = { const struct target *target_table[] = {
&tgt_dll, &tgt_dll,
#ifdef WITH_T_XNF
&tgt_xnf, &tgt_xnf,
#endif
0 0
}; };
/* /*
* $Log: targets.cc,v $ * $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 * Revision 1.11 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig. * conditional ident string using autoconfig.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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) static void show_lpm(ivl_lpm_t net)
{ {
unsigned idx; unsigned idx;
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
switch (ivl_lpm_type(net)) { switch (ivl_lpm_type(net)) {
@ -191,19 +192,11 @@ static void show_lpm(ivl_lpm_t net)
case IVL_LPM_ADD: { case IVL_LPM_ADD: {
fprintf(out, " LPM_ADD %s: <width=%u>\n", fprintf(out, " LPM_ADD %s: <width=%u>\n",
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
for (idx = 0 ; idx < width ; idx += 1) fprintf(out, " Q: %s\n", ivl_nexus_name(ivl_lpm_q(net, 0)));
fprintf(out, " Q %u: %s\n", idx, nex = ivl_lpm_data(net, 0);
ivl_nexus_name(ivl_lpm_q(net, idx))); fprintf(out, " DataA: %s\n", nex? ivl_nexus_name(nex) : "");
for (idx = 0 ; idx < width ; idx += 1) { ivl_nexus_t nex = ivl_lpm_datab(net, 0);
ivl_nexus_t nex = ivl_lpm_data(net, idx); fprintf(out, " DataB: %s\n", nex? ivl_nexus_name(nex) : "");
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) : "");
}
break; break;
} }
@ -367,6 +360,15 @@ static void show_lpm(ivl_lpm_t net)
break; 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: default:
fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n", fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n",
ivl_lpm_type(net), ivl_lpm_type(net),
@ -396,17 +398,13 @@ static void show_assign_lval(ivl_lval_t lval, unsigned ind)
} else { } else {
unsigned pp; 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, "", fprintf(out, "%*spart_off=%u {%s", ind, "",
ivl_lval_part_off(lval), ivl_lval_part_off(lval),
ivl_nexus_name(nex)); ivl_nexus_name(nex));
fprintf(out, "<nptrs=%u>", ivl_nexus_ptrs(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"); fprintf(out, "}\n");
} }
} }
@ -481,6 +479,17 @@ static void show_statement(ivl_statement_t net, unsigned ind)
break; 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: { case IVL_ST_CONDIT: {
ivl_expr_t ex = ivl_stmt_cond_expr(net); ivl_expr_t ex = ivl_stmt_cond_expr(net);
ivl_statement_t t = ivl_stmt_cond_true(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; 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: case IVL_ST_DELAY:
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net)); fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
show_statement(ivl_stmt_sub_stmt(net), ind+2); 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) static void show_signal(ivl_signal_t net)
{ {
unsigned pin; unsigned idx;
ivl_nexus_t nex;
const char*type = "?"; const char*type = "?";
const char*port = ""; const char*port = "";
const char*sign = ivl_signal_signed(net)? "signed" : "unsigned"; const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";
@ -702,61 +722,60 @@ static void show_signal(ivl_signal_t net)
break; break;
} }
fprintf(out, " %s %s %s[%u] %s\n", type, sign, port, nex = ivl_signal_nex(net);
ivl_signal_pins(net), ivl_signal_basename(net));
for (pin = 0 ; pin < ivl_signal_pins(net) ; pin += 1) { fprintf(out, " %s %s %s[%d:%d] %s <width=%u> nexus=%s\n",
unsigned idx; type, sign, port,
ivl_nexus_t nex = ivl_signal_pin(net, pin); ivl_signal_msb(net), ivl_signal_lsb(net),
ivl_signal_basename(net), ivl_signal_width(net),
fprintf(out, " [%u]: nexus=%s\n", pin, ivl_nexus_name(nex)); 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);
} else { for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
fprintf(out, " ?[%u] (%s0, %s1)\n", ivl_net_const_t con;
ivl_nexus_ptr_pin(ptr), dr0, dr1); 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) { for (idx = 0 ; idx < ivl_signal_attr_cnt(net) ; idx += 1) {
ivl_attribute_t atr = ivl_signal_attr_val(net, pin); ivl_attribute_t atr = ivl_signal_attr_val(net, idx);
switch (atr->type) { switch (atr->type) {
case IVL_ATT_STR: 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, ", %s", ivl_nexus_name(nex));
} }
fprintf(out, ");\n"); fprintf(out, "); <width=%u>\n", ivl_logic_width(net));
npins = ivl_logic_attr_cnt(net); npins = ivl_logic_attr_cnt(net);
for (idx = 0 ; idx < npins ; idx += 1) { for (idx = 0 ; idx < npins ; idx += 1) {
@ -953,6 +972,11 @@ int target_design(ivl_design_t des)
/* /*
* $Log: stub.c,v $ * $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 * Revision 1.90 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -89,6 +89,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
break; break;
case IVL_EX_SIGNAL: case IVL_EX_SIGNAL:
#if 0
/* If the signal node is narrower then the signal /* If the signal node is narrower then the signal
itself, then this is a part select so I'm going itself, then this is a part select so I'm going
to need to evaluate the expression. to need to evaluate the expression.
@ -112,7 +113,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
} else { } else {
continue; continue;
} }
#else
continue;
#endif
case IVL_EX_MEMORY: case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) { 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 /* If this is a part select, then the value was
calculated above. Otherwise, just pass the calculated above. Otherwise, just pass the
signal. */ signal. */
#if 0
if (ivl_expr_width(expr) != if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) { ivl_signal_pins(ivl_expr_signal(expr))) {
break; break;
@ -182,6 +186,11 @@ static void draw_vpi_taskfunc_args(const char*call_string,
vvp_signal_label(ivl_expr_signal(expr))); vvp_signal_label(ivl_expr_signal(expr)));
continue; continue;
} }
#else
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
continue;
#endif
case IVL_EX_VARIABLE: { case IVL_EX_VARIABLE: {
ivl_variable_t var = ivl_expr_variable(expr); 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 $ * $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 * Revision 1.9 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_priv.h" # 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) if (swid > res.wid)
swid = res.wid; swid = res.wid;
if (ivl_signal_type(sig) == IVL_SIT_REG) { /* XXXX I forget how to do part selects here. */
/* If this is a REG (a variable) then I can do a vector assert(lsi == 0);
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);
}
}
/* 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. */ /* Pad the signal value with zeros. */
if (swid < res.wid) { 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 $ * $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 * Revision 1.110 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_config.h" # 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 * Return the base of an allocated vector in the thread. The bits
* are marked allocated in the process. * are marked allocated in the process.
* *
* clr_bector * clr_vector
* Clear a vector previously allocated. * Clear a vector previously allocated.
* *
* The thread vector allocator also keeps a lookaside of expression * The thread vector allocator also keeps a lookaside of expression
@ -193,6 +193,11 @@ extern unsigned thread_count;
/* /*
* $Log: vvp_priv.h,v $ * $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 * Revision 1.28 2004/01/20 21:00:47 steve
* Isolate configure from containing config.h * Isolate configure from containing config.h
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_priv.h" # 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); ivl_signal_t sig = ivl_lval_sig(lval);
unsigned part_off = ivl_lval_part_off(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)) { if (ivl_lval_mux(lval)) {
assert(wid == 1); assert(wid == 1);
if ((ivl_signal_pins(sig)-1) <= 0xffffU) { 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); 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 { } else {
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n", fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(sig), idx+part_off, bit, wid); 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); unsigned part_off = ivl_lval_part_off(lval);
assert(ivl_lval_mux(lval) == 0); 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, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n", fprintf(vvp_out, " %%assign/v0 V_%s, %u, %u;\n",
vvp_signal_label(sig), part_off+idx, delay, bit); 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; skip_set_flag = 1;
} }
if (bit_limit > ivl_lval_pins(lval)) if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_pins(lval); bit_limit = ivl_lval_width(lval);
if (mem) { if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) { 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); set_to_memory(mem, idx, bidx);
cur_rbit += 1; cur_rbit += 1;
} }
#if 0
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1) for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
set_to_memory(mem, idx, 0); set_to_memory(mem, idx, 0);
#else
assert(0);
#endif
} else { } else {
unsigned bidx = res.base < 4 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); : (res.base+cur_rbit);
set_to_lvariable(lval, 0, bidx, bit_limit); set_to_lvariable(lval, 0, bidx, bit_limit);
cur_rbit += 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; skip_set_flag = 1;
} }
if (bit_limit > ivl_lval_pins(lval)) if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_pins(lval); bit_limit = ivl_lval_width(lval);
if (mem) { if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) { 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 for (idx = bit_limit
; idx < ivl_lval_pins(lval) ; idx += 1) ; idx < ivl_lval_width(lval) ; idx += 1)
set_to_memory(mem, idx, 0); set_to_memory(mem, idx, 0);
} else { } 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; idx = 0;
while (idx < bit_limit) { while (idx < bit_limit) {
unsigned cnt = 1; unsigned cnt = 1;
@ -341,19 +357,19 @@ static int show_stmt_assign_vector(ivl_statement_t net)
&& (bits[cur_rbit] == bits[cur_rbit+cnt])) && (bits[cur_rbit] == bits[cur_rbit+cnt]))
cnt += 1; cnt += 1;
set_to_lvariable(lval, idx, fprintf(vvp_out, " %%mov %u, %u, %u;\n",
bitchar_to_idx(bits[cur_rbit]), vect.base+idx,
cnt); bitchar_to_idx(bits[cur_rbit]),
cnt);
cur_rbit += cnt; cur_rbit += cnt;
idx += cnt; idx += cnt;
} }
/* write out the value into the .var. */
if (bit_limit < ivl_lval_pins(lval)) { fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
unsigned cnt = ivl_lval_pins(lval) - bit_limit; vvp_signal_label(sig), vect.base, vect.wid);
set_to_lvariable(lval, bit_limit, 0, cnt); clr_vector(vect);
}
} }
if (skip_set_flag) { if (skip_set_flag) {
@ -490,138 +506,6 @@ static int show_stmt_assign_nb(ivl_statement_t net)
del = 0; 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); { struct vector_info res = draw_eval_expr(rval, 0);
unsigned wid = res.wid; unsigned wid = res.wid;
@ -653,10 +537,10 @@ static int show_stmt_assign_nb(ivl_statement_t net)
skip_set_flag = 1; skip_set_flag = 1;
} }
if (bit_limit > ivl_lval_pins(lval)) if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_pins(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 unsigned bidx = res.base < 4
? res.base ? 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) if (mem)
assign_to_memory(mem, idx, 0, delay); assign_to_memory(mem, idx, 0, delay);
else if (del != 0) else if (del != 0)
@ -939,8 +823,7 @@ static int show_stmt_cassign(ivl_statement_t net)
{ {
ivl_lval_t lval; ivl_lval_t lval;
ivl_signal_t lsig; ivl_signal_t lsig;
unsigned idx; ivl_expr_t rval;
char*tmp_label;
assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0); lval = ivl_stmt_lval(net, 0);
@ -948,16 +831,22 @@ static int show_stmt_cassign(ivl_statement_t net)
lsig = ivl_lval_sig(lval); lsig = ivl_lval_sig(lval);
assert(lsig != 0); assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mux(lval) == 0);
assert(ivl_signal_pins(lsig) == ivl_stmt_nexus_count(net));
assert(ivl_lval_part_off(lval) == 0); assert(ivl_lval_part_off(lval) == 0);
tmp_label = strdup(vvp_signal_label(lsig)); if ( (rval = ivl_stmt_rval(net)) ) {
for (idx = 0 ; idx < ivl_stmt_nexus_count(net) ; idx += 1) {
fprintf(vvp_out, " %%cassign V_%s[%u], %s;\n", struct vector_info rvec = draw_eval_expr(rval, STUFF_OK_47);
tmp_label, idx, fprintf(vvp_out, " %%cassign/v V_%s, %u, %u;\n",
draw_net_input(ivl_stmt_nexus(net, idx))); 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; return 0;
} }
@ -976,10 +865,8 @@ static int show_stmt_deassign(ivl_statement_t net)
assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(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;\n", vvp_signal_label(lsig));
fprintf(vvp_out, " %%deassign V_%s[%u], 1;\n",
vvp_signal_label(lsig), idx);
}
return 0; return 0;
} }
@ -1113,7 +1000,7 @@ static int show_stmt_force(ivl_statement_t net)
assert(lsig != 0); assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0); assert(ivl_lval_part_off(lval) == 0);
#if 0
force_functor_label += 1; force_functor_label += 1;
tmp_label = strdup(vvp_signal_label(lsig)); tmp_label = strdup(vvp_signal_label(lsig));
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) { 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", fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
force_functor_label, idx); force_functor_label, idx);
} }
#else
fprintf(stderr, "XXXX I forgot how to implement %%force\n");
#endif
return 0; return 0;
} }
@ -1222,7 +1112,7 @@ static int show_stmt_release(ivl_statement_t net)
done before we start. */ done before we start. */
if (ivl_stmt_lvals(net) == 0) if (ivl_stmt_lvals(net) == 0)
return 0; return 0;
#if 0
assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0); 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", fprintf(vvp_out, " %%release V_%s[%u];\n",
vvp_signal_label(lsig), idx); vvp_signal_label(lsig), idx);
} }
#else
fprintf(stderr, "XXXX I forgot how to implement %%release\n");
#endif
return 0; return 0;
} }
@ -1626,6 +1518,11 @@ int draw_func_definition(ivl_scope_t scope)
/* /*
* $Log: vvp_process.c,v $ * $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 * Revision 1.93 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_priv.h" # 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); sptr = ivl_nexus_ptr_sig(nptr);
if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) { 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; return result;
} }
cptr = ivl_nexus_ptr_con(nptr); cptr = ivl_nexus_ptr_con(nptr);
if (cptr) { if (cptr) {
/* Constants should have exactly 1 pin, with a vector
result. */
assert(nptr_pin == 0);
const char*bits = ivl_const_bits(cptr); const char*bits = ivl_const_bits(cptr);
ivl_drive_t drive; ivl_drive_t drive;
switch (bits[nptr_pin]) { unsigned idx;
case '0':
drive = ivl_nexus_ptr_drive0(nptr); char*dp = result;
if (drive == IVL_DR_HiZ) strcpy(dp, "C4<");
sprintf(result, "C<z>"); dp += strlen(dp);
else
sprintf(result, "C<%s0>", drive_string(drive)); for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
break; switch (bits[ivl_const_width(cptr)-idx-1]) {
case '1': case '0':
drive = ivl_nexus_ptr_drive1(nptr); drive = ivl_nexus_ptr_drive0(nptr);
if (drive == IVL_DR_HiZ) if (drive == IVL_DR_HiZ) {
sprintf(result, "C<z>"); *dp++ = 'z';
else } else {
sprintf(result, "C<%s1>", drive_string(drive)); *dp++ = '0';
break; }
default: break;
sprintf(result, "C<%c>", bits[nptr_pin]); 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; 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_DIVIDE:
case IVL_LPM_MOD: case IVL_LPM_MOD:
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1) case IVL_LPM_PART:
if (ivl_lpm_q(lpm, idx) == nex) { if (ivl_lpm_q(lpm, 0) == nex) {
sprintf(result, "L_%p[%u]", lpm, idx); sprintf(result, "L_%p", lpm);
return result; return result;
} }
break; break;
@ -520,13 +540,13 @@ const char* draw_net_input(ivl_nexus_t nex)
if (ndrivers == 0) { if (ndrivers == 0) {
switch (res) { switch (res) {
case IVL_SIT_TRI: case IVL_SIT_TRI:
nex_private = "C<z>"; nex_private = "C4<z>";
break; break;
case IVL_SIT_TRI0: case IVL_SIT_TRI0:
nex_private = "C<0>"; nex_private = "C4<0>";
break; break;
case IVL_SIT_TRI1: case IVL_SIT_TRI1:
nex_private = "C<1>"; nex_private = "C4<1>";
break; break;
default: default:
assert(0); assert(0);
@ -566,7 +586,7 @@ const char* draw_net_input(ivl_nexus_t nex)
} }
} }
for ( ; idx < inst+4 ; idx += 1) for ( ; idx < inst+4 ; idx += 1)
fprintf(vvp_out, ", C<z>"); fprintf(vvp_out, ", C4<z>");
fprintf(vvp_out, ";\n"); 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) static void draw_net_in_scope(ivl_signal_t sig)
{ {
unsigned idx;
int msb = ivl_signal_msb(sig); int msb = ivl_signal_msb(sig);
int lsb = ivl_signal_lsb(sig); int lsb = ivl_signal_lsb(sig);
typedef const char*const_charp; typedef const char*const_charp;
const_charp* args; const char* arg;
const char*signed_flag = ivl_signal_signed(sig)? "/s" : ""; 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)) if (ivl_signal_local(sig))
return; return;
args = (const_charp*)calloc(ivl_signal_pins(sig), sizeof(char*)); /* Connect the pin of the signal to something. */
{
/* Connect all the pins of the signal to something. */ ivl_nexus_t nex = ivl_signal_nex(sig);
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) { arg = draw_net_input(nex);
ivl_nexus_t nex = ivl_signal_pin(sig, idx);
args[idx] = 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_signal_label(sig), signed_flag,
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb); vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb, arg);
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
fprintf(vvp_out, ", %s", args[idx]);
}
fprintf(vvp_out, ";\n");
free(args);
} }
static void draw_delay(ivl_net_logic_t lptr) 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) { for ( ; pdx < inst+4 ; pdx += 1) {
fprintf(vvp_out, ", C<%c>", identity_val); fprintf(vvp_out, ", C4<%c>", identity_val);
} }
fprintf(vvp_out, ";\n"); 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 width = ivl_lpm_width(net);
unsigned idx; unsigned idx;
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t a = ivl_lpm_data(net, idx); assert(width > 0);
if (a) { ivl_nexus_t nex = ivl_lpm_data(net, 0);
fprintf(vvp_out, ", "); ivl_signal_t sig = 0;
draw_input_from_net(a);
} else { ivl_nexus_ptr_t np;
fprintf(vvp_out, ", C<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;
} }
for (idx = 0 ; idx < width ; idx += 1) { assert(sig != 0);
ivl_nexus_t b = ivl_lpm_datab(net, idx);
if (b) { fprintf(vvp_out, ", V_%s", vvp_signal_label(sig));
fprintf(vvp_out, ", ");
draw_input_from_net(b); sig = 0;
} else { nex = ivl_lpm_datab(net, 0);
fprintf(vvp_out, ", C<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) 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"); 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) static void draw_lpm_in_scope(ivl_lpm_t net)
{ {
switch (ivl_lpm_type(net)) { switch (ivl_lpm_type(net)) {
@ -1474,6 +1511,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_add(net); draw_lpm_add(net);
return; return;
case IVL_LPM_PART:
draw_lpm_part(net);
return;
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NE:
draw_lpm_eq(net); draw_lpm_eq(net);
@ -1624,6 +1665,11 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/* /*
* $Log: vvp_scope.c,v $ * $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 * Revision 1.103 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # 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 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 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 \ 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 \ functor.o fvectors.o npmos.o part.o resolv.o stop.o symbols.o ufunc.o \
vthread.o schedule.o statistics.o tables.o udp.o memory.o force.o event.o \ codes.o \
logic.o delay.o words.o $V 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) ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps. # 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) * 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 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 by assignment events. It does have output, though, and its output is
propagated into the net of functors in the usual way. propagated into the net of functors in the usual way.
Therefore, the .var statement implicitly also creates .functors A variable gets its value by assignments from procedural code: %set
addressed by the label of the variable. It is in fact the functors and %assign. These instructions write values to the port-0 input. From
that behavioral code reads when the value of the variable (or net) is there, the value is held.
read by behavioral code. If the .var represents a vector of .functors,
the index of the LSB is always, from the perspective of vvp, ZERO. The
<msb>,<lsb> details are there only for the benefit of VPI support.
The variable .functor implicitly has two inputs. The first is the Behavioral code can also invoke %cassign/v statements that work like
value that gets set by assignments. The second input is connected to %set/v, but instead write to port-1 of the variable node. Writes to
the driving expression of a procedural continuous assignments. port-1 of a variable activate continuous assign mode, where the values
Variable functors have an extra internal bit that tells if a written to port-0 are ignored. The continuous assign mode remains
procedural continuous assignment is active. The %cassign opcode active until a long(1) is written to port-3 (a command port).
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 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: 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 code. The syntax of a .net statement is also similar to but not
exactly the same as the .var statement: exactly the same as the .var statement:
<label> .net "name", <msb>, <lsb>, <symbols_list>; <label> .net "name", <msb>, <lsb>, <symbol>;
<label> .net/s "name", <msb>, <lsb>, <symbols_list>; <label> .net/s "name", <msb>, <lsb>, <symbol>;
Like a .var statement, the .net statement creates a VPI object with Like a .var statement, the .net statement creates a VPI object with
the basename and dimensions given as parameters, but unlike a .var the basename and dimensions given as parameters. The symbol is a
statement, it creates no functors. The symbol list is a list of functor that feeds into the vector of the net, and the vpiHandle
functors that feed into each bit of the vector, and the vpiHandle holds references to that functor.
holds references to those functors that are fed it.
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 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 represents. This label does not map to a functor, so only references
@ -443,7 +438,19 @@ resolution function.
<label> .resolv tri1, <symbols_list>; <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 A force statement creates functors that represent a Verilog force
statement. 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 <signal> is the label of the functor that drives the signal that is
being forced. 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: STRUCTURAL ARITHMETIC STATEMENTS:
The various Verilog arithmetic operators (+-*/%) are available to The various Verilog arithmetic operators (+-*/%) ar avaiable to
structural contexts even though they do not fit into nice neat structural contexts as two-input functors that take in vectors. All of
functors. These operators are not in general bitwise, so special these operators take two inputs and generate a fixed width output. The
measures are needed to make them work in a functor environment. We input vectors will be padded if needed to get the desired output width.
create special statement types for the various arithmetic operators.
<label> .arith/sub <wid>, <symbols_list>; <label> .arith/sub <wid>, <A>, <B>;
<label> .arith/sum <wid>, <symbols_list>; <label> .arith/sum <wid>, <A>, <B>;
<label> .arith/mult <wid>, <symbols_list>; <label> .arith/mult <wid>, <A>, <B>;
<label> .arith/div <wid>, <symbols_list>; <label> .arith/div <wid>, <A>, <B>;
<label> .arith/mod <wid>, <symbols_list>; <label> .arith/mod <wid>, <A>, <B>;
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.
In all cases, there are no width limits, so long as the width is fixed.
STRUCTURAL COMPARE STATEMENTS: 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 hierarchical relationships can get confused. The behavior of erroneous
code is undefined. 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 * Threads and scopes
The Verilog ``disable'' statement deserves some special mention 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "arith.h" # include "arith.h"
@ -30,57 +30,11 @@
# include <malloc.h> # include <malloc.h>
#endif #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) { for (unsigned idx = 0 ; idx < wid ; idx += 1)
vvp_ipoint_t ptr = ipoint_index(base,idx); x_val_.set_bit(idx, BIT4_X);
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);
}
} }
@ -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) void vvp_arith_div::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
#if 0
put(i, val); put(i, val);
vvp_ipoint_t base = ipoint_make(i,0); 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; result = 0 - result;
output_val_(base, push, 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) 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) void vvp_arith_mod::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
#if 0
put(i, val); put(i, val);
vvp_ipoint_t base = ipoint_make(i,0); 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); output_val_(base, push, a%b);
#else
fprintf(stderr, "XXXX forgot how to implement vvp_arith_mod::set\n");
#endif
} }
// Multiplication // Multiplication
void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned) void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
#if 0
put(i, val); put(i, val);
vvp_ipoint_t base = ipoint_make(i,0); 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); 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) void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
{ {
unsigned char *a, *b, *sum; unsigned char *a, *b, *sum;
@ -284,62 +251,67 @@ void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
delete[]b; delete[]b;
delete[]a; delete[]a;
} }
#endif
// Addition // 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; vvp_arith_sum::~vvp_arith_sum()
unsigned pbit = 0; {
unsigned long carry = 0; }
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) { for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base, idx); vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
functor_t obj = functor_index(ptr); 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 (cur == BIT4_X) {
if (val & 0xaa) { vvp_send_vec4(net->out, x_val_);
output_x_(base, push);
return; return;
} }
// Accumulate the sum of the input bits. value.set_bit(idx, cur);
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;
}
} }
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 * 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 * plus one, so we further reduce the operation to adding in the
* inverted value and adding a correction. * 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); unsigned port = ptr.port();
vvp_ipoint_t base = ipoint_make(i,0);
unsigned page = 0; switch (port) {
unsigned pbit = 0; case 0:
unsigned long carry = 0; op_a_ = bit;
break;
case 1:
op_b_ = bit;
break;
default:
assert(0);
}
/* There are 3 values subtracted from the first parameter, so vvp_net_t*net = ptr.ptr();
there are three 2s complements, so three ~X +1. That's why
the sum_ starts with 3. */
sum_[0] = 3;
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) { for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base, idx); vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
functor_t obj = functor_index(ptr); 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 (cur == BIT4_X) {
if (val & 0xaa) { vvp_send_vec4(net->out, x_val_);
output_x_(base, push);
return; return;
} }
// Accumulate the sum of the input bits. Add in the value.set_bit(idx, cur);
// 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;
}
} }
output_val_(base, push); vvp_send_vec4(net->out, value);
} }
vvp_cmp_eq::vvp_cmp_eq(unsigned wid) vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
: vvp_arith_(wid) : vvp_arith_(wid)
{ {
} }
#if 0
void vvp_cmp_eq::set(vvp_ipoint_t i, bool push, unsigned val, unsigned) void vvp_cmp_eq::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
put(i, val); 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); put_oval(out_val, push);
} }
#endif
vvp_cmp_ne::vvp_cmp_ne(unsigned wid) vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
: vvp_arith_(wid) : vvp_arith_(wid)
{ {
} }
#if 0
void vvp_cmp_ne::set(vvp_ipoint_t i, bool push, unsigned val, unsigned) void vvp_cmp_ne::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
put(i, val); 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); put_oval(out_val, push);
} }
#endif
vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid, bool flag) vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid, bool flag)
: vvp_arith_(wid), signed_flag_(flag) : vvp_arith_(wid), signed_flag_(flag)
{ {
} }
#if 0
void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i, void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i,
bool push, bool push,
unsigned val, unsigned val,
@ -561,7 +522,7 @@ void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i,
put_oval(out_val, push); put_oval(out_val, push);
} }
#endif
vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag) 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) void vvp_cmp_ge::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str)
{ {
set_base(i, push, val, str, 1); set_base(i, push, val, str, 1);
} }
#endif
vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag) vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
: vvp_cmp_gtge_base_(wid, flag) : vvp_cmp_gtge_base_(wid, flag)
{ {
} }
#if 0
void vvp_cmp_gt::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str) void vvp_cmp_gt::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str)
{ {
set_base(i, push, val, str, 0); set_base(i, push, val, str, 0);
} }
#endif
#if 0
void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned) void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
put(i, val); 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) void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{ {
put(i, val); 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 $ * $Log: arith.cc,v $
* Revision 1.30 2004/10/04 01:10:58 steve * Revision 1.31 2004/12/11 02:31:29 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "functor.h" # include "functor.h"
# include "vvp_net.h"
// base class for arithmetic functors // base class for arithmetic functors
class vvp_arith_ : public functor_s { class vvp_arith_ : public vvp_net_fun_t {
public: public:
explicit vvp_arith_(unsigned wid) : wid_(wid) {}; explicit vvp_arith_(unsigned wid);
protected: protected:
unsigned wid_; unsigned wid_;
protected: vvp_vector4_t op_a_;
void output_x_(vvp_ipoint_t base, bool push, unsigned val = 2); vvp_vector4_t op_b_;
void output_val_(vvp_ipoint_t base, bool push, unsigned long sum); // Precalculated X result for propagation.
}; vvp_vector4_t x_val_;
// 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);
}; };
/* /*
@ -89,20 +77,26 @@ class vvp_arith_mod : public vvp_arith_ {
void wide(vvp_ipoint_t base, bool push); void wide(vvp_ipoint_t base, bool push);
}; };
class vvp_arith_sum : public vvp_wide_arith_ { class vvp_arith_sum : public vvp_arith_ {
public: 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: 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_ { class vvp_cmp_eq : public vvp_arith_ {
@ -169,66 +163,10 @@ class vvp_shiftr : public vvp_arith_ {
/* /*
* $Log: arith.h,v $ * $Log: arith.h,v $
* Revision 1.19 2004/10/04 01:10:58 steve * Revision 1.20 2004/12/11 02:31:29 steve
* Clean up spurious trailing white space. * Rework of internals to carry vectors through nexus instead
* * of single bits. Make the ivl, tgt-vvp and vvp initial changes
* Revision 1.18 2004/09/22 16:44:07 steve * down this path.
* 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.
* *
*/ */
#endif #endif

View File

@ -19,11 +19,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "pointers.h" # include "pointers.h"
# include "vvp_net.h"
# include "memory.h" # include "memory.h"
# include "vthread.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_ADDI(vthread_t thr, vvp_code_t code);
extern bool of_AND(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_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_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_MEM(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); 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_ASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_BLEND(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_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_CMPIU(vthread_t thr, vvp_code_t code);
extern bool of_CMPS(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); 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_JMP0XZ(vthread_t thr, vvp_code_t code);
extern bool of_JMP1(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_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_MEM(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_NX(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); 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_OR(vthread_t thr, vvp_code_t code);
extern bool of_ORR(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_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_MEM(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(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); extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
@ -133,7 +131,7 @@ struct vvp_code_s {
union { union {
unsigned long number; unsigned long number;
vvp_ipoint_t iptr; vvp_net_t *net;
vvp_code_t cptr; vvp_code_t cptr;
vvp_memory_t mem; vvp_memory_t mem;
struct __vpiHandle*handle; struct __vpiHandle*handle;
@ -143,7 +141,7 @@ struct vvp_code_s {
union { union {
unsigned bit_idx[2]; unsigned bit_idx[2];
vvp_ipoint_t iptr2; vvp_net_t *net2;
vvp_code_t cptr2; vvp_code_t cptr2;
struct ufunc_core*ufunc_core_ptr; struct ufunc_core*ufunc_core_ptr;
}; };
@ -170,6 +168,11 @@ extern vvp_code_t codespace_null(void);
/* /*
* $Log: codes.h,v $ * $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 * Revision 1.66 2004/06/19 15:52:53 steve
* Add signed modulus operator. * Add signed modulus operator.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "arith.h" # 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} }, { "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and", of_AND, 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} }, { "%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/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/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} }, { "%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} }, { "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%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/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/u", of_CMPU, 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} }, { "%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/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ri", of_CVT_RI, 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} }, { "%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} }, { "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%delayx", of_DELAYX, 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} }, { "%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/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%jmp/1", of_JMP1, 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} }, { "%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/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/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} }, { "%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", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or/r", of_ORR, 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} }, { "%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/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/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} }, { "%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 * 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; symbol_value_t val;
val.num = ipt; val.net = net;
sym_set_value(sym_functors, label, val); 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); assert(sym_functors);
symbol_value_t val = sym_get_value(sym_functors, label); 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 /* 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 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 vpiReg:
case vpiIntegerVar: { case vpiIntegerVar: {
__vpiSignal*sig = (__vpiSignal*)vpi; __vpiSignal*sig = (__vpiSignal*)vpi;
return vvp_fvector_get(sig->bits, idx); return sig->node;
} }
case vpiNamedEvent: { case vpiNamedEvent: {
@ -253,10 +250,9 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
} }
} }
/* Failing that, look for a general functor. */ /* Failing that, look for a general functor. */
vvp_ipoint_t tmp = lookup_functor_symbol(label); vvp_net_t*tmp = lookup_functor_symbol(label);
if (tmp)
tmp = ipoint_index(tmp, idx);
return tmp; 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; static struct resolv_list_s*resolv_list = 0;
struct resolv_list_s { struct resolv_list_s {
virtual ~resolv_list_s() { }
struct resolv_list_s*next; struct resolv_list_s*next;
virtual bool resolve(bool mes = false) = 0; 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 vvp_net_resolv_list_s: public resolv_list_s {
struct functor_resolv_list_s: public resolv_list_s { // node to locate
char*source; char*source;
unsigned idx; // port to be driven by the located node.
vvp_ipoint_t port; vvp_net_ptr_t port;
virtual bool resolve(bool mes); 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) { if (tmp) {
functor_t fport = functor_index(tmp); // Link the input port to the located output.
functor_t iobj = functor_index(port); vvp_net_t*net = port.ptr();
net->port[port.port()] = tmp->out;
iobj->port[ipoint_port(port)] = fport->out; tmp->out = port;
fport->out = port;
free(source); free(source);
return true; return true;
} }
if (mes) if (mes)
fprintf(stderr, "unresolved functor reference: %s\n", source); fprintf(stderr, "unresolved vvp_net reference: %s\n", source);
return false; return false;
} }
inline static 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->source = lab;
res->idx = idx;
resolv_submit(res); resolv_submit(res);
} }
/* /*
* Generic functor reference lookup. * Generic functor reference lookup.
*/ */
struct functor_gen_resolv_list_s: public resolv_list_s { struct functor_gen_resolv_list_s: public resolv_list_s {
char*source; char*source;
unsigned idx; vvp_net_t**ref;
vvp_ipoint_t *ref;
virtual bool resolve(bool mes); virtual bool resolve(bool mes);
}; };
bool functor_gen_resolv_list_s::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) { if (tmp) {
*ref = tmp; *ref = tmp;
@ -370,14 +368,13 @@ bool functor_gen_resolv_list_s::resolve(bool mes)
return false; 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 = struct functor_gen_resolv_list_s*res =
new struct functor_gen_resolv_list_s; new struct functor_gen_resolv_list_s;
res->ref = ref; res->ref = ref;
res->source = lab; res->source = lab;
res->idx = idx;
resolv_submit(res); 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 * connected to my input ports. For each source functor that I
* find, connect the output of that functor to the indexed * find, connect the output of that functor to the indexed
* input by inserting myself (complete with the port number in * 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. * 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) { for (unsigned idx = 0; idx < argc; idx += 1) {
/* Find the functor for this input. This assumes that input_connect(fdx, idx, argv[idx].text);
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);
} }
} }
@ -731,7 +736,7 @@ void const_functor_s::set(vvp_ipoint_t p, bool, unsigned val, unsigned)
assert(0); assert(0);
} }
#if 0
static vvp_ipoint_t make_const_functor(unsigned val, static vvp_ipoint_t make_const_functor(unsigned val,
unsigned str0, unsigned str0,
unsigned str1) unsigned str1)
@ -744,9 +749,11 @@ static vvp_ipoint_t make_const_functor(unsigned val,
return fdx; return fdx;
} }
#endif
/* Lookup a functor[idx] and save the ipoint in *ref. */ /* Lookup a functor[idx] and save the ipoint in *ref. */
#if 0
static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx) static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
{ {
if (lab == 0) 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); functor_ref_lookup(ref, lab, idx);
return; return;
} }
free(lab); free(lab);
} }
#endif
#if 0
static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid) static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
{ {
for (unsigned i=1; i < wid; i++) { 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; fu->base_ = fdx;
} }
} }
#endif
static void make_arith(vvp_arith_ *arith, static void make_arith(vvp_arith_ *arith,
char*label, long wid, char*label, long wid,
unsigned argc, struct symb_s*argv) unsigned argc, struct symb_s*argv)
{ {
vvp_ipoint_t fdx = functor_allocate(wid); vvp_net_t* ptr = new vvp_net_t;
functor_define(fdx, arith); ptr->fun = arith;
define_functor_symbol(label, fdx); define_functor_symbol(label, ptr);
free(label); free(label);
make_extra_outputs(fdx, wid); assert(argc == 2);
inputs_connect(ptr, argc, argv);
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);
}
free(argv); free(argv);
} }
@ -904,21 +899,13 @@ void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
{ {
assert( wid > 0 ); assert( wid > 0 );
if ((argc % wid) != 0) { if (argc != 2) {
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label); 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);
compile_errors += 1; compile_errors += 1;
return; return;
} }
vvp_arith_ *arith = new vvp_arith_sum(wid); vvp_arith_ *arith = new vvp_arith_sum(wid);
make_arith(arith, label, wid, argc, argv); make_arith(arith, label, wid, argc, argv);
} }
@ -988,6 +975,7 @@ static void make_shift(vvp_arith_*arith,
char*label, long wid, char*label, long wid,
unsigned argc, struct symb_s*argv) unsigned argc, struct symb_s*argv)
{ {
#if 0
vvp_ipoint_t fdx = functor_allocate(wid); vvp_ipoint_t fdx = functor_allocate(wid);
functor_define(fdx, arith); functor_define(fdx, arith);
@ -1015,7 +1003,9 @@ static void make_shift(vvp_arith_*arith,
inputs_connect(ptr, tmp_argc, tmp_argv); inputs_connect(ptr, tmp_argc, tmp_argv);
} }
#else
fprintf(stderr, "XXXX make_shift not implemented\n");
#endif
free(argv); 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) void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
{ {
assert(argc <= 4); assert(argc <= 4);
vvp_net_fun_t* obj = 0;
functor_t obj = 0;
if (strcmp(type,"tri") == 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) { } 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) { } 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) { } 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) { } else if (strcmp(type,"trior") == 0) {
obj = new table_functor_s(ft_TRIOR, 6, 6); obj = new table_functor_s(ft_TRIOR);
} else { } else {
fprintf(stderr, "invalid resolver type: %s\n", type); 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) { if (obj) {
vvp_ipoint_t fdx = functor_allocate(1); vvp_net_t*net = new vvp_net_t;
functor_define(fdx, obj); define_functor_symbol(label, net);
define_functor_symbol(label, fdx); inputs_connect(net, argc, argv);
inputs_connect(fdx, argc, argv);
} }
free(type); free(type);
free(label); free(label);
free(argv); 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, void compile_force(char*label, struct symb_s signal,
unsigned argc, struct symb_s*argv) unsigned argc, struct symb_s*argv)
{ {
#if 0
vvp_ipoint_t ifofu = functor_allocate(argc); vvp_ipoint_t ifofu = functor_allocate(argc);
define_functor_symbol(label, ifofu); define_functor_symbol(label, ifofu);
@ -1121,7 +1108,9 @@ void compile_force(char*label, struct symb_s signal,
// connect the force expression, one bit. // connect the force expression, one bit.
inputs_connect(iobj, 1, &argv[i]); inputs_connect(iobj, 1, &argv[i]);
} }
#else
fprintf(stderr, "XXXX compile_force not implemented\n");
#endif
free(argv); free(argv);
free(signal.text); free(signal.text);
free(label); free(label);
@ -1161,7 +1150,7 @@ void compile_udp_functor(char*label, char*type,
{ {
struct vvp_udp_s *u = udp_find(type); struct vvp_udp_s *u = udp_find(type);
assert (argc == u->nin); assert (argc == u->nin);
#if 0
functor_t udp = new udp_functor_s(u); functor_t udp = new udp_functor_s(u);
unsigned nfun = (argc+3)/4; unsigned nfun = (argc+3)/4;
@ -1186,6 +1175,9 @@ void compile_udp_functor(char*label, char*type,
if (u->sequ) if (u->sequ)
udp->put_oval(u->init, false); 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 naddr,
unsigned argc, struct symb_s *argv) unsigned argc, struct symb_s *argv)
{ {
#if 0
vvp_memory_t mem = memory_find(memid); vvp_memory_t mem = memory_find(memid);
free(memid); free(memid);
assert(mem); assert(mem);
@ -1226,6 +1219,9 @@ void compile_memory_port(char *label, char *memid,
inputs_connect(ix, argc, argv); inputs_connect(ix, argc, argv);
free(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) 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; break;
} }
functor_ref_lookup(&code->iptr, functor_ref_lookup(&code->net, opa->argv[idx].symb.text);
opa->argv[idx].symb.text,
opa->argv[idx].symb.idx);
break; break;
case OA_FUNC_PTR2: case OA_FUNC_PTR2:
@ -1336,27 +1330,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break; break;
} }
if (strcmp(opa->argv[idx].symb.text, "C<0>") == 0) { functor_ref_lookup(&code->net2, opa->argv[idx].symb.text);
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);
}
break; break;
case OA_NUMBER: 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; unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
vvp_ipoint_t fdx = functor_allocate(wid); vvp_fun_signal*vsig = new vvp_fun_signal(wid);
define_functor_symbol(label, fdx); vvp_net_t*node = new vvp_net_t;
node->fun = vsig;
functor_t fu = new var_functor_s [wid]; define_functor_symbol(label, node);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
functor_define(ipoint_index(fdx, idx), fu+idx);
}
count_functors_var += wid;
/* Make the vpiHandle for the reg. */ /* Make the vpiHandle for the reg. */
vvp_fvector_t vec = vvp_fvector_continuous_new(wid, fdx);
vpiHandle obj = (signed_flag > 1) ? vpiHandle obj = (signed_flag > 1) ?
vpip_make_int(name, msb, lsb, vec) : vpip_make_int(name, msb, lsb, node) :
vpip_make_reg(name, msb, lsb, signed_flag!=0, vec); vpip_make_reg(name, msb, lsb, signed_flag!=0, node);
compile_vpi_symbol(label, obj); compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj); vpip_attach_to_current_scope(obj);
@ -1540,23 +1509,35 @@ void compile_variable(char*label, char*name, int msb, int lsb,
free(name); 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, void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
unsigned argc, struct symb_s*argv) unsigned argc, struct symb_s*argv)
{ {
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1; unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
vvp_fvector_t vec = vvp_fvector_new(wid); vvp_net_t*node = new vvp_net_t;
//define_fvector_symbol(label, vec);
assert(argc == wid); vvp_fun_signal*vsig = new vvp_fun_signal(wid);
node->fun = vsig;
for (unsigned idx = 0 ; idx < wid ; idx += 1) { /* Add the label into the functor symbol table. */
vvp_ipoint_t *ref = vvp_fvector_member(vec, idx); define_functor_symbol(label, node);
functor_reference(ref, argv[idx].text, argv[idx].idx);
} assert(argc == 1);
/* Connect the source to my input. */
inputs_connect(node, 1, argv);
/* Make the vpiHandle for the reg. */ /* 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); compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(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 $ * $Log: compile.cc,v $
* Revision 1.175 2004/10/04 01:10:58 steve * Revision 1.176 2004/12/11 02:31:29 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include <stdio.h> # include <stdio.h>
# include "parse_misc.h" # include "parse_misc.h"
# include "vpi_user.h" # include "vpi_user.h"
# include "vvp_net.h"
/* /*
* The functions described here are the compile time support * 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. * Connect a list of symbols to a contiguous set of ipoints.
* Constants C<?> are handled by setting the ival of the ipoint. * 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 * 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 * 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, extern void compile_resolver(char*label, char*type,
unsigned argc, struct symb_s*argv); 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. * 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 $ * $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 * Revision 1.56 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "event.h" # include "event.h"
@ -33,87 +33,56 @@
# include <malloc.h> # include <malloc.h>
#endif #endif
event_functor_s::event_functor_s(edge_t e) inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
: edge(e) {
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; threads = 0;
} }
event_functor_s::~event_functor_s() vvp_fun_edge::~vvp_fun_edge()
{}
/*
* 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()
{ {
} }
void named_event_functor_s::set(vvp_ipoint_t ptr, bool push, void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
unsigned val, unsigned str)
{ {
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; vthread_t tmp = threads;
threads = 0; threads = 0;
vthread_schedule_list(tmp); 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, void compile_event(char*label, char*type,
unsigned argc, struct symb_s*argv) 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) if (strcmp(type,"posedge") == 0)
edge = vvp_edge_posedge; edge = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0) else if (strcmp(type,"negedge") == 0)
@ -137,37 +106,19 @@ void compile_event(char*label, char*type,
else if (strcmp(type,"edge") == 0) else if (strcmp(type,"edge") == 0)
edge = vvp_edge_anyedge; 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); define_functor_symbol(label, ptr);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
free(label); free(label);
/* Run through the arguments looking for the functors that are inputs_connect(ptr, argc, argv);
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);
} }
/* /*
@ -177,17 +128,12 @@ void compile_event(char*label, char*type,
*/ */
void compile_named_event(char*label, char*name) 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); vvp_net_t*fdx = 0;
functor_define(fdx, fp);
vpiHandle obj = vpip_make_named_event(name, fdx); 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); compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj); vpip_attach_to_current_scope(obj);
@ -197,52 +143,9 @@ void compile_named_event(char*label, char*name)
/* /*
* $Log: event.cc,v $ * $Log: event.cc,v $
* Revision 1.14 2004/10/04 01:10:59 steve * Revision 1.15 2004/12/11 02:31:29 steve
* Clean up spurious trailing white space. * Rework of internals to carry vectors through nexus instead
* * of single bits. Make the ivl, tgt-vvp and vvp initial changes
* Revision 1.13 2003/11/26 01:47:18 steve * down this path.
* 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)
* *
*/ */

View File

@ -19,44 +19,50 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "functor.h" # include "vvp_net.h"
# include "pointers.h"
/* /*
* Event / edge detection functors * Event / edge detection functors
*/ */
struct event_functor_s: public edge_inputs_functor_s, public waitable_hooks_s { /*
typedef unsigned short edge_t; * A "waitable" functor is one that the %wait instruction can wait
explicit event_functor_s(edge_t e); * on. This includes the infrastructure needed to hold threads.
virtual ~event_functor_s(); */
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str); struct waitable_hooks_s {
edge_t edge; 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 public:
= VVP_EDGE(0,1) typedef unsigned short edge_t;
| VVP_EDGE(0,2) explicit vvp_fun_edge(edge_t e);
| VVP_EDGE(0,3)
| VVP_EDGE(2,1)
| VVP_EDGE(3,1)
;
const event_functor_s::edge_t vvp_edge_negedge virtual ~vvp_fun_edge();
= VVP_EDGE(1,0)
| VVP_EDGE(1,2)
| VVP_EDGE(1,3)
| VVP_EDGE(2,0)
| VVP_EDGE(3,0)
;
const event_functor_s::edge_t vvp_edge_anyedge = 0x7bde; void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
const event_functor_s::edge_t vvp_edge_none = 0;
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 * 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 * 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 struct callback_functor_s *vvp_fvector_make_callback
(vvp_fvector_t, event_functor_s::edge_t = vvp_edge_none); (vvp_fvector_t, event_functor_s::edge_t = vvp_edge_none);
#endif
/* /*
* $Log: event.h,v $ * $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 * Revision 1.5 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "codes.h" # 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) bool of_FORCE(vthread_t thr, vvp_code_t cp)
{ {
#if 0
unsigned wid = cp->bit_idx[0]; unsigned wid = cp->bit_idx[0];
for (unsigned i=0; i<wid; i++) { 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. // on its forced value.
fofu->set(ifofu, false, fofu->get_oval(), fofu->get_ostr()); fofu->set(ifofu, false, fofu->get_oval(), fofu->get_ostr());
} }
#else
fprintf(stderr, "XXXX forgot how to implement %%force\n");
#endif
return true; 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) bool of_RELEASE(vthread_t thr, vvp_code_t cp)
{ {
#if 0
vvp_ipoint_t itgt = cp->iptr; vvp_ipoint_t itgt = cp->iptr;
functor_t tgt = functor_index(itgt); functor_t tgt = functor_index(itgt);
if (release_force(itgt, tgt)) if (release_force(itgt, tgt))
tgt->enable(itgt); tgt->enable(itgt);
#else
fprintf(stderr, "XXXX forgot how to implement %%release\n");
#endif
return true; return true;
} }
@ -213,84 +219,14 @@ bool var_functor_s::deassign(vvp_ipoint_t itgt)
return false; 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 $ * $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 * Revision 1.8 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "pointers.h" # include "pointers.h"
@ -277,15 +277,6 @@ unsigned functor_get(vvp_ipoint_t ptr)
// Special infrastructure functor types // 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 // The extra_outputs_functor_s class is for devices that require
// multiple inputs and outputs. // multiple inputs and outputs.
// ->set redirects the job to the base_, who knows what shall be done. // ->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 $ * $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 * Revision 1.52 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "parse_misc.h" # include "parse_misc.h"
@ -101,6 +101,7 @@
".net" { return K_NET; } ".net" { return K_NET; }
".net/s" { return K_NET_S; } ".net/s" { return K_NET_S; }
".param" { return K_PARAM; } ".param" { return K_PARAM; }
".part" { return K_PART; }
".resolv" { return K_RESOLV; } ".resolv" { return K_RESOLV; }
".scope" { return K_SCOPE; } ".scope" { return K_SCOPE; }
".shift/l" { return K_SHIFTL; } ".shift/l" { return K_SHIFTL; }
@ -182,6 +183,11 @@ int yywrap()
/* /*
* $Log: lexor.lex,v $ * $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 * Revision 1.43 2004/06/30 02:15:57 steve
* Add signed LPM divide. * 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "logic.h" # include "logic.h"
@ -38,36 +38,14 @@
* to 4 inputs. * 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) : table(t)
{ {
count_functors_table += 1; count_functors_table += 1;
assert(str0 <= 7);
assert(str1 <= 7);
odrive0 = str0;
odrive1 = str1;
} }
table_functor_s::~table_functor_s() 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, vvp_delay_t delay, unsigned ostr0, unsigned ostr1,
unsigned argc, struct symb_s*argv) unsigned argc, struct symb_s*argv)
{ {
functor_t obj; table_functor_s* obj = 0;
if (strcmp(type, "OR") == 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) { } 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) { } 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) { } else if (strcmp(type, "BUFIF0") == 0) {
obj = new vvp_bufif_s(true,false, ostr0, ostr1); obj = new vvp_bufif_s(true,false, ostr0, ostr1);
} else if (strcmp(type, "BUFIF1") == 0) { } else if (strcmp(type, "BUFIF1") == 0) {
obj = new vvp_bufif_s(false,false, ostr0, ostr1); obj = new vvp_bufif_s(false,false, ostr0, ostr1);
#endif
} else if (strcmp(type, "BUFZ") == 0) { } 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) { } else if (strcmp(type, "PMOS") == 0) {
obj = new vvp_pmos_s; obj = new vvp_pmos_s;
@ -111,7 +89,7 @@ void compile_functor(char*label, char*type,
} else if (strcmp(type, "RNMOS") == 0) { } else if (strcmp(type, "RNMOS") == 0) {
obj = new vvp_rnmos_s; obj = new vvp_rnmos_s;
#endif
} else if (strcmp(type, "MUXX") == 0) { } else if (strcmp(type, "MUXX") == 0) {
obj = new table_functor_s(ft_MUXX); 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); obj = new table_functor_s(ft_EEQ);
} else if (strcmp(type, "NAND") == 0) { } 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) { } 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) { } 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) { } else if (strcmp(type, "NOTIF0") == 0) {
obj = new vvp_bufif_s(true,true, ostr0, ostr1); obj = new vvp_bufif_s(true,true, ostr0, ostr1);
} else if (strcmp(type, "NOTIF1") == 0) { } else if (strcmp(type, "NOTIF1") == 0) {
obj = new vvp_bufif_s(false,true, ostr0, ostr1); obj = new vvp_bufif_s(false,true, ostr0, ostr1);
#endif
} else if (strcmp(type, "XNOR") == 0) { } 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) { } else if (strcmp(type, "XOR") == 0) {
obj = new table_functor_s(ft_XOR, ostr0, ostr1); obj = new table_functor_s(ft_XOR);
} else { } else {
yyerror("invalid functor type."); yyerror("invalid functor type.");
@ -153,61 +131,22 @@ void compile_functor(char*label, char*type,
free(type); free(type);
assert(argc <= 4); assert(argc <= 4);
vvp_ipoint_t fdx = functor_allocate(1); vvp_net_t*net = new vvp_net_t;
functor_define(fdx, obj);
define_functor_symbol(label, fdx); define_functor_symbol(label, net);
free(label); free(label);
obj->delay = delay; inputs_connect(net, argc, argv);
inputs_connect(fdx, argc, argv);
free(argv); free(argv);
} }
/* /*
* $Log: logic.cc,v $ * $Log: logic.cc,v $
* Revision 1.13 2004/10/04 01:10:59 steve * Revision 1.14 2004/12/11 02:31:29 steve
* Clean up spurious trailing white space. * Rework of internals to carry vectors through nexus instead
* * of single bits. Make the ivl, tgt-vvp and vvp initial changes
* Revision 1.12 2002/09/06 04:56:29 steve * down this path.
* 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)
* *
*/ */

View File

@ -1,7 +1,7 @@
#ifndef __logic_H #ifndef __logic_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "functor.h" # include "vvp_net.h"
# include <stddef.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: public:
typedef const unsigned char *truth_t; 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 ~table_functor_s();
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
private: private:
truth_t table; truth_t table;
}; };
@ -66,26 +66,10 @@ extern const unsigned char ft_var[];
/* /*
* $Log: logic.h,v $ * $Log: logic.h,v $
* Revision 1.7 2003/07/30 01:13:29 steve * Revision 1.8 2004/12/11 02:31:29 steve
* Add support for triand and trior. * Rework of internals to carry vectors through nexus instead
* * of single bits. Make the ivl, tgt-vvp and vvp initial changes
* Revision 1.6 2002/08/29 03:04:01 steve * down this path.
* 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)
* *
*/ */
#endif // __logic_H #endif // __logic_H

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com) * 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 1 and 1 --> 1
otherwise x otherwise x
* %assign <var-label>, <delay>, <bit> * %assign <var-label>, <delay>, <bit> (DEPRECATED -- use %assign/v0)
* %assign/d <var-label>, <delay>, <bit> * %assign/d <var-label>, <delay>, <bit> (DEPRECATED -- need %assign/v0/d)
* %assign/v0 <var-label>, <delay>, <bit>
This does a non-blocking assignment to a variable. The <label> This does a non-blocking assignment to a variable. The <label>
identifies the affected variable, and the <delay> gives the delay when 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 instruction, except that the <delay> specifies one of the index
registers, that contain a calculated delay. 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> * %assign/m <memory-label>, <delay>, <bit>
This instruction does a non-blocking assignment to a bit in a memory 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 by index register 3. Bit address zero is the LSB of the first memory
word. 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> * %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 This may not work on all platforms. If run-time debugging is compiled
out, then this function is a no-op. 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 * %deassign <var-label>
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>
Deactivate and disconnect a procedural continuous assignment to a Deactivate and disconnect a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable. <wid> variable. The <var-label> identifies the affected variable.
specifies the how many bits to deassign.
* %cmp/u <bit-l>, <bit-r>, <wid> * %cmp/u <bit-l>, <bit-r>, <wid>
@ -294,7 +297,7 @@ bits.
This instruction loads an immediate value into the addressed index This instruction loads an immediate value into the addressed index
register. The index register holds numeric values, so the <value> is a 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 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. 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 the calling thread until the child ends. If the child is already
ended, then the %join does not block or yield the thread. 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> * %load/m <bit>, <memory-label>
This instruction loads a value from a memory bit into the specified 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 objects don't really exist (they are only named indirection into the
netlist) this instruction indexes into the .net list of bits. 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> * %load/wr <bit>, <vpi-label>
This instruction reads a real value from the vpi-like object to a word 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 %release <functor-label> ; remove the force
* %set <var-label>, <bit>
* %set/v <var-label>, <bit>, <wid> * %set/v <var-label>, <bit>, <wid>
This sets a bit of a variable, and is used to implement blocking 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "parse_misc.h" # 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_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
%token K_ARITH_SUB K_ARITH_SUM %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_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_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
%token K_UDP K_UDP_C K_UDP_S %token K_UDP K_UDP_C K_UDP_S
%token K_MEM K_MEM_P K_MEM_I %token K_MEM K_MEM_P K_MEM_I
@ -181,6 +181,12 @@ statement
compile_resolver($1, $3, obj.cnt, obj.vect); 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 /* Force statements are very much like functors. They are
compiled to functors of a different mode. */ compiled to functors of a different mode. */
@ -566,10 +572,6 @@ symbol
{ $$.text = $1; { $$.text = $1;
$$.idx = 0; $$.idx = 0;
} }
| T_SYMBOL '[' T_NUMBER ']'
{ $$.text = $1;
$$.idx = $3;
}
; ;
symbol_opt symbol_opt
@ -635,6 +637,11 @@ int compile_design(const char*path)
/* /*
* $Log: parse.y,v $ * $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 * Revision 1.60 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "resolv.h" # include "resolv.h"
@ -25,6 +25,7 @@
# include "statistics.h" # include "statistics.h"
# include <assert.h> # include <assert.h>
#if 0
/* /*
* A signal value is unambiguous if the top 4 bits and the bottom 4 * 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 * 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); 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 $ * $Log: resolv.cc,v $
* Revision 1.17 2003/03/13 04:36:57 steve * Revision 1.18 2004/12/11 02:31:30 steve
* Remove the obsolete functor delete functions. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
# include "functor.h" # include "vvp_net.h"
/* /*
* This functor type resolves its inputs using the verilog method of * This functor type resolves its inputs using the verilog method of
* combining signals, and outputs that resolved value. The puller * combining signals, and outputs that resolved value. The puller
* value is also blended with the result. This helps with the * 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: public:
explicit resolv_functor_s(unsigned char hiz_value); explicit resolv_functor(vvp_scaler_t hiz_value);
~resolv_functor_s(); ~resolv_functor();
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
void recv_vec8(vvp_vector8_t bit);
private: private:
unsigned char istr[4]; vvp_vector8_t driven_;
unsigned char hiz_; vvp_scaler_t hiz_;
}; };
/* /*
* $Log: resolv.h,v $ * $Log: resolv.h,v $
* Revision 1.8 2003/03/13 04:36:57 steve * Revision 1.9 2004/12/11 02:31:30 steve
* Remove the obsolete functor delete functions. * Rework of internals to carry vectors through nexus instead
* * of single bits. Make the ivl, tgt-vvp and vvp initial changes
* Revision 1.7 2002/08/12 01:35:08 steve * down this path.
* 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.
* *
*/ */
#endif #endif

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "schedule.h" # include "schedule.h"
@ -43,30 +43,19 @@ unsigned long count_time_pool = 0;
/* /*
* The event_s and event_time_s structures implement the Verilog * The event_s and event_time_s structures implement the Verilog
* stratified event queue. The event_time_s objects are one per time * stratified event queue.
* step. Each time step in turn contains a list of event_s objects *
* that are the actual events. * 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 { 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; struct event_s*next;
virtual ~event_s() { }
void* operator new (size_t); virtual void run_run(void) =0;
void operator delete(void*obj, size_t s);
}; };
const unsigned TYPE_GEN = 0;
const unsigned TYPE_THREAD = 1;
const unsigned TYPE_PROP = 2;
const unsigned TYPE_ASSIGN = 3;
struct event_time_s { struct event_time_s {
vvp_time64_t delay; vvp_time64_t delay;
@ -81,43 +70,50 @@ struct event_time_s {
void operator delete(void*obj, size_t 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. ** 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 struct event_time_s* time_free_list = 0;
static const unsigned TIME_CHUNK_COUNT = 8192 / sizeof(struct event_time_s); 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) 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->thr = thr;
cur->type = TYPE_THREAD;
vthread_mark_scheduled(thr); vthread_mark_scheduled(thr);
if (push_flag && (delay == 0)) { 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) void functor_s::schedule(vvp_time64_t delay, bool nba_flag)
{ {
#if 0
struct event_s*cur = new event_s; struct event_s*cur = new event_s;
cur->funp = this; cur->funp = this;
cur->type = TYPE_PROP; cur->type = TYPE_PROP;
schedule_event_(cur, delay, nba_flag? SEQ_NBASSIGN:SEQ_ACTIVE); 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) void schedule_assign(vvp_ipoint_t fun, unsigned char val, vvp_time64_t delay)
{ {
struct event_s*cur = new event_s; 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); 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, void schedule_generic(vvp_gen_event_t obj, unsigned char val,
vvp_time64_t delay, bool sync_flag) 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->obj = obj;
cur->val = val; cur->val = val;
cur->type= TYPE_GEN;
schedule_event_(cur, delay, sync_flag? SEQ_ROSYNC : SEQ_ACTIVE); schedule_event_(cur, delay, sync_flag? SEQ_ROSYNC : SEQ_ACTIVE);
} }
@ -459,10 +469,7 @@ void schedule_simulate(void)
struct event_s*sync_cur; struct event_s*sync_cur;
while ( (sync_cur = pull_sync_event()) ) { while ( (sync_cur = pull_sync_event()) ) {
assert(sync_cur->type == TYPE_GEN); sync_cur->run_run();
if (sync_cur->obj && sync_cur->obj->run) {
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
}
delete sync_cur; delete sync_cur;
} }
@ -499,6 +506,8 @@ void schedule_simulate(void)
ctim->active->next = cur->next; ctim->active->next = cur->next;
} }
cur->run_run();
#if 0
switch (cur->type) { switch (cur->type) {
case TYPE_THREAD: case TYPE_THREAD:
count_thread_events += 1; count_thread_events += 1;
@ -529,7 +538,7 @@ void schedule_simulate(void)
break; break;
} }
#endif
delete (cur); delete (cur);
} }
@ -539,10 +548,7 @@ void schedule_simulate(void)
for (struct event_s*sync_cur = pull_sync_event() for (struct event_s*sync_cur = pull_sync_event()
; sync_cur ; sync_cur = pull_sync_event()) { ; sync_cur ; sync_cur = pull_sync_event()) {
assert(sync_cur->type == TYPE_GEN); sync_cur->run_run();
if (sync_cur->obj && sync_cur->obj->run)
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
delete (sync_cur); delete (sync_cur);
} }
@ -556,6 +562,11 @@ void schedule_simulate(void)
/* /*
* $Log: schedule.cc,v $ * $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 * Revision 1.28 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *
@ -570,8 +581,5 @@ void schedule_simulate(void)
* *
* Revision 1.24 2003/02/22 02:52:06 steve * Revision 1.24 2003/02/22 02:52:06 steve
* Check for stopped flag in certain strategic points. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vthread.h" # include "vthread.h"
# include "pointers.h" # include "pointers.h"
# include "vvp_net.h"
/* /*
* This causes a thread to be scheduled for execution. The schedule * 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 * Create an assignment event. The val passed here will be assigned to
* the specified input when the delay times out. * the specified input when the delay times out.
*/ */
extern void schedule_assign(vvp_ipoint_t fun, unsigned char val, extern void schedule_assign_vector(vvp_net_ptr_t ptr,
vvp_time64_t delay); vvp_vector4_t val,
vvp_time64_t delay);
/* /*
@ -108,28 +110,15 @@ extern unsigned long count_event_pool;
/* /*
* $Log: schedule.h,v $ * $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 * Revision 1.16 2003/09/09 00:56:45 steve
* Reimpelement scheduler to divide nonblocking assign queue out. * Reimpelement scheduler to divide nonblocking assign queue out.
* *
* Revision 1.15 2003/02/22 02:52:06 steve * Revision 1.15 2003/02/22 02:52:06 steve
* Check for stopped flag in certain strategic points. * 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 #endif

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
/* /*
@ -39,6 +39,7 @@
*/ */
# include "config.h" # include "config.h"
# include "vvp_net.h"
/* /*
* This is the basic type of a symbol table. It is opaque. Don't even * 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 { typedef struct symbol_value_s {
union { union {
unsigned long num; vvp_net_t*net;
void*ptr; void*ptr;
unsigned long num;
}; };
} symbol_value_t; } symbol_value_t;
@ -79,6 +81,11 @@ symbol_value_t sym_get_value(symbol_table_t tbl, const char*key);
/* /*
* $Log: symbols.h,v $ * $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 * Revision 1.4 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig. * conditional ident string using autoconfig.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "compile.h" # include "compile.h"
@ -138,7 +138,7 @@ void compile_ufunc(char*label, char*code, unsigned wid,
unsigned portc, struct symb_s*portv, unsigned portc, struct symb_s*portv,
unsigned retc, struct symb_s*retv) unsigned retc, struct symb_s*retv)
{ {
#if 0
/* Create an array of vvp_ipoint_t pointers, that point to the /* Create an array of vvp_ipoint_t pointers, that point to the
.var bits of the function ports. Do this for the input .var bits of the function ports. Do this for the input
ports and the output port. */ ports and the output port. */
@ -232,10 +232,18 @@ void compile_ufunc(char*label, char*code, unsigned wid,
} }
inputs_connect(ibase, argc, argv); inputs_connect(ibase, argc, argv);
#else
fprintf(stderr, "XXXX compile_ufunc not implemented.\n");
#endif
} }
/* /*
* $Log: ufunc.cc,v $ * $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 * Revision 1.4 2003/07/03 20:03:36 steve
* Remove the vvp_cpoint_t indirect code pointer. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
/* /*
@ -96,85 +96,6 @@ struct __vpiCallback* new_vpi_callback()
return obj; 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 * 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 vpiReg:
case vpiNet: case vpiNet:
case vpiIntegerVar: case vpiIntegerVar:
/* Attach the callback to the vvp_fun_signal node by
putting it in the vpi_callbacks list. */
struct __vpiSignal*sig; struct __vpiSignal*sig;
sig = reinterpret_cast<__vpiSignal*>(data->obj); sig = reinterpret_cast<__vpiSignal*>(data->obj);
/* Create callback functors, if necessary, to do the vvp_fun_signal*sig_fun;
value change detection and carry the callback sig_fun = dynamic_cast<vvp_fun_signal*>(sig->node->fun);
objects. */ assert(sig_fun);
if (sig->callback == 0) {
sig->callback = vvp_fvector_make_callback(sig->bits);
assert(sig->callback);
}
/* Attach the __vpiCallback object to the signals /* Attach the __vpiCallback object to the signal. */
callback functors. */ obj->next = sig_fun->vpi_callbacks;
obj->next = sig->callback->cb_handle; sig_fun->vpi_callbacks = obj;
sig->callback->cb_handle = obj;
break; break;
case vpiRealVar: case vpiRealVar:
@ -512,25 +430,25 @@ void callback_execute(struct __vpiCallback*cur)
} }
/* /*
* A callback_functor_s functor uses its set method to detect value * A vvp_fun_signal uses this method to run its callbacks whenever it
* changes. When a value comes in, the __vpiCallback objects that are * has a value change. If the cb_rtn is non-nil, then call the
* associated with this callback functor are all called. * callback function. If the cb_rtn pointer is nil, then the object
* has been marked for deletion. Free it.
*/ */
void vvp_fun_signal::run_vpi_callbacks()
void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
{ {
struct __vpiCallback *next = cb_handle; struct __vpiCallback *next = vpi_callbacks;
struct __vpiCallback *prev = 0; struct __vpiCallback *prev = 0;
while (next) { while (next) {
struct __vpiCallback * cur = next; struct __vpiCallback*cur = next;
next = cur->next; next = cur->next;
if (cur->cb_data.cb_rtn != 0) { if (cur->cb_data.cb_rtn != 0) {
if (cur->cb_data.value) { if (cur->cb_data.value) {
switch (cur->cb_data.value->format) { switch (cur->cb_data.value->format) {
case vpiScalarVal: case vpiScalarVal:
cur->cb_data.value->value.scalar = val; cur->cb_data.value->value.scalar = value(0);
break; break;
case vpiSuppressVal: case vpiSuppressVal:
break; break;
@ -546,7 +464,7 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
} else if (prev == 0) { } else if (prev == 0) {
cb_handle = next; vpi_callbacks = next;
cur->next = 0; cur->next = 0;
vpi_free_object(&cur->base); vpi_free_object(&cur->base);
@ -556,89 +474,21 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
cur->next = 0; cur->next = 0;
vpi_free_object(&cur->base); vpi_free_object(&cur->base);
} }
} }
} }
/* /*
* $Log: vpi_callback.cc,v $ * $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 * Revision 1.34 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *
* Revision 1.33 2004/02/18 02:51:59 steve * Revision 1.33 2004/02/18 02:51:59 steve
* Fix type mismatches of various VPI functions. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vpi_priv.h" # include "vpi_priv.h"
@ -86,7 +86,7 @@ static const struct __vpirt vpip_named_event_rt = {
0 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*) struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)
malloc(sizeof(struct __vpiNamedEvent)); malloc(sizeof(struct __vpiNamedEvent));
@ -142,6 +142,11 @@ void vpip_run_named_event_callbacks(vpiHandle ref)
/* /*
* $Log: vpi_event.cc,v $ * $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 * Revision 1.9 2003/05/04 20:43:36 steve
* Event callbacks support vpi_remove_cb. * Event callbacks support vpi_remove_cb.
* *

View File

@ -19,11 +19,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vpi_user.h" # include "vpi_user.h"
# include "pointers.h" # include "pointers.h"
# include "vvp_net.h"
# include "memory.h" # include "memory.h"
/* /*
@ -177,16 +178,14 @@ struct __vpiSignal {
unsigned signed_flag : 1; unsigned signed_flag : 1;
unsigned isint_ : 1; // original type was integer unsigned isint_ : 1; // original type was integer
/* The represented value is here. */ /* The represented value is here. */
vvp_fvector_t bits; vvp_net_t*node;
/* This is the callback event functor */
struct callback_functor_s *callback;
}; };
extern vpiHandle vpip_make_int(const char*name, int msb, int lsb, 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, 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, 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 * These methods support the vpi creation of events. The name string
@ -200,12 +199,12 @@ struct __vpiNamedEvent {
/* Parent scope of this object. */ /* Parent scope of this object. */
struct __vpiScope*scope; struct __vpiScope*scope;
/* The functor, used for %set operations. */ /* The functor, used for %set operations. */
vvp_ipoint_t funct; vvp_net_t*funct;
/* List of callbacks interested in this event. */ /* List of callbacks interested in this event. */
struct __vpiCallback*callbacks; 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_run_named_event_callbacks(vpiHandle ref);
extern void vpip_real_value_change(struct __vpiCallback*cbh, extern void vpip_real_value_change(struct __vpiCallback*cbh,
vpiHandle ref); vpiHandle ref);
@ -418,6 +417,11 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
/* /*
* $Log: vpi_priv.h,v $ * $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 * Revision 1.59 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
/* /*
@ -107,7 +107,7 @@ static int signal_get(int code, vpiHandle ref)
case _vpiNexusId: case _vpiNexusId:
if (rfp->msb == rfp->lsb) if (rfp->msb == rfp->lsb)
return vvp_fvector_get(rfp->bits, 0); return (int)rfp->node;
else else
return 0; return 0;
@ -178,10 +178,12 @@ static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
? (rfp->msb - rfp->lsb + 1) ? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 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) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx); bits[idx] = vsig->value(idx);
bits[idx] = functor_get(fptr);
} }
unsigned hwid = (wid+2) / 3 + 1; 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->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 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 /* The result will use a character for each 8 bits of the
vector. Add one extra character for the highest bits that 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; char tmp = 0;
int bitnr; int bitnr;
for(bitnr=wid-1; bitnr>=0; bitnr--){ for(bitnr=wid-1; bitnr>=0; bitnr--){
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, bitnr);
tmp <<= 1; tmp <<= 1;
switch (functor_get(fptr)) { switch (vsig->value(bitnr)) {
case 0: case BIT4_0:
break; break;
case 1: case BIT4_1:
tmp |= 1; tmp |= 1;
break; break;
default: default:
@ -254,6 +256,9 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
unsigned wid = (rfp->msb >= rfp->lsb) unsigned wid = (rfp->msb >= rfp->lsb)
? (rfp->msb - rfp->lsb + 1) ? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1); : (rfp->lsb - rfp->msb + 1);
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
char *rbuf = 0; char *rbuf = 0;
switch (vp->format) { 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); assert(wid <= 8 * sizeof vp->value.integer);
vp->value.integer = 0; vp->value.integer = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx); switch (vsig->value(idx)) {
switch (functor_get(fptr)) { case BIT4_0:
case 0:
break; break;
case 1: case BIT4_1:
vp->value.integer |= 1<<idx; vp->value.integer |= 1<<idx;
break; break;
default: default:
@ -278,18 +282,17 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
break; break;
case vpiScalarVal: { case vpiScalarVal: {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, 0); switch (vsig->value(0)) {
switch (functor_get(fptr)) { case BIT4_0:
case 0:
vp->value.scalar = vpi0; vp->value.scalar = vpi0;
break; break;
case 1: case BIT4_1:
vp->value.scalar = vpi1; vp->value.scalar = vpi1;
break; break;
case 2: case BIT4_X:
vp->value.scalar = vpiX; vp->value.scalar = vpiX;
break; break;
case 3: case BIT4_Z:
vp->value.scalar = vpiZ; vp->value.scalar = vpiZ;
break; break;
} }
@ -301,8 +304,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf = need_result_buf(wid+1, RBUF_VAL); rbuf = need_result_buf(wid+1, RBUF_VAL);
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx); rbuf[wid-idx-1] = "01xz"[vsig->value(idx)];
rbuf[wid-idx-1] = "01xz"[functor_get(fptr)];
} }
rbuf[wid] = 0; rbuf[wid] = 0;
vp->value.str = rbuf; vp->value.str = rbuf;
@ -316,8 +318,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf[hwid] = 0; rbuf[hwid] = 0;
hval = 0; hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx); hval = hval | (vsig->value(idx) << 2*(idx % 4));
hval = hval | (functor_get(fptr) << 2*(idx % 4));
if (idx%4 == 3) { if (idx%4 == 3) {
hwid -= 1; hwid -= 1;
@ -353,8 +354,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf[hwid] = 0; rbuf[hwid] = 0;
hval = 0; hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx); hval = hval | (vsig->value(idx) << 2*(idx % 3));
hval = hval | (functor_get(fptr) << 2*(idx % 3));
if (idx%3 == 2) { if (idx%3 == 2) {
hwid -= 1; hwid -= 1;
@ -400,21 +400,20 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
op->aval = op->bval = 0; op->aval = op->bval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx); switch (vsig->value(idx)) {
switch (functor_get(fptr)) { case BIT4_0:
case 0:
op->aval &= ~(1 << obit); op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit); op->bval &= ~(1 << obit);
break; break;
case 1: case BIT4_1:
op->aval |= (1 << obit); op->aval |= (1 << obit);
op->bval &= ~(1 << obit); op->bval &= ~(1 << obit);
break; break;
case 2: case BIT4_X:
op->aval |= (1 << obit); op->aval |= (1 << obit);
op->bval |= (1 << obit); op->bval |= (1 << obit);
break; break;
case 3: case BIT4_Z:
op->aval &= ~(1 << obit); op->aval &= ~(1 << obit);
op->bval |= (1 << obit); op->bval |= (1 << obit);
break; break;
@ -430,51 +429,6 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
break; 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: default:
fprintf(stderr, "vvp internal error: get_value: " fprintf(stderr, "vvp internal error: get_value: "
"value type %u not implemented." "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, static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
unsigned val, unsigned str, unsigned long dly =0) unsigned val, unsigned str, unsigned long dly =0)
{ {
vvp_ipoint_t ptr = vvp_fvector_get(rfp->bits,idx); fprintf(stderr, "XXXX functor_poke not implemented\n");
if (dly > 0) {
schedule_assign(ptr, val, dly);
} else {
functor_t fu = functor_index(ptr);
fu->put_ostr(val, str, true);
}
} }
static void signal_put_stringval(struct __vpiSignal*rfp, unsigned wid, 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 * to minimize the code modifications. Icarus implements integers
* as 'reg signed [31:0]'. * 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); vpiHandle obj = vpip_make_net(name, msb,lsb, true, vec);
struct __vpiSignal*rfp = (struct __vpiSignal*)obj; 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. * Construct a vpiReg object. It's like a net, except for the type.
*/ */
vpiHandle vpip_make_reg(const char*name, int msb, int lsb, 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); vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
obj->vpi_type = &vpip_reg_rt; 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. * and point to the specified functor for the lsb.
*/ */
vpiHandle vpip_make_net(const char*name, int msb, int 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(); struct __vpiSignal*obj = allocate_vpiSignal();
obj->base.vpi_type = &vpip_net_rt; 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->lsb = lsb;
obj->signed_flag = signed_flag? 1 : 0; obj->signed_flag = signed_flag? 1 : 0;
obj->isint_ = false; obj->isint_ = false;
obj->bits = vec; obj->node = node;
obj->callback = 0;
obj->scope = vpip_peek_current_scope(); 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 $ * $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 * Revision 1.62 2004/05/19 03:26:25 steve
* Support delayed/non-blocking assignment to reals and others. * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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); assert(addr < thr->nbits);
unsigned idx = addr % (CPU_WORD_BITS/2); unsigned idx = addr % (CPU_WORD_BITS/2);
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, 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; 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. * 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; 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) bool of_ASSIGN_D(vthread_t thr, vvp_code_t cp)
{ {
#if 0
assert(cp->bit_idx[0] < 4); assert(cp->bit_idx[0] < 4);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]); 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); 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; return true;
} }
@ -544,15 +566,10 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
unsigned delay = cp->bit_idx[0]; unsigned delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1]; unsigned bit = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < wid ; idx += 1) { vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
unsigned char bit_val = thr_get_bit(thr, bit); vvp_net_ptr_t ptr (cp->net, 0);
schedule_assign(iptr, bit_val, delay); schedule_assign_vector(ptr, value, delay);
if (bit >= 4)
bit += 1;
}
return true; 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) 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]); 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); vvp_ipoint_t itmp = ipoint_index(cp->iptr, thr->words[0].w_int);
schedule_assign(itmp, bit_val, cp->bit_idx[0]); schedule_assign(itmp, bit_val, cp->bit_idx[0]);
#else
fprintf(stderr, "XXXX forgot how to implement %%assign/x0\n");
#endif
return true; return true;
} }
@ -624,6 +645,34 @@ bool of_BREAKPOINT(vthread_t thr, vvp_code_t cp)
return true; 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) bool of_CMPS(vthread_t thr, vvp_code_t cp)
{ {
unsigned eq = 1; unsigned eq = 1;
@ -879,6 +928,21 @@ bool of_CVT_VR(vthread_t thr, vvp_code_t cp)
return true; 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) bool of_DELAY(vthread_t thr, vvp_code_t cp)
{ {
//printf("thread %p: %%delay %lu\n", thr, cp->number); //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; 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) bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
{ {
assert(cp->bit_idx[0] >= 4); 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) 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; unsigned idx = thr->words[cp->bit_idx[1]].w_int;
vvp_ipoint_t ptr = vvp_fvector_get(sig->bits, idx); vvp_fun_signal*fun = dynamic_cast<vvp_fun_signal*>(sig->node->fun);
thr_put_bit(thr, cp->bit_idx[0], functor_get(ptr)); assert(sig != 0);
vvp_bit4_t val = fun->value(idx);
thr_put_bit(thr, cp->bit_idx[0], val);
return true; 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) bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
{ {
assert(cp->bit_idx[0] >= 4); assert(cp->bit_idx[0] >= 4);
assert(cp->bit_idx[1] > 0); assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[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); /* For the %load to work, the functor must actually be a
thr_put_bit(thr, bit, functor_get(iptr)); 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; 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[0] >= 4);
assert(cp->bit_idx[1] < 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); 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)); 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; 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}; 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) bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
{ {
unsigned char val = thr_get_bit(thr, cp->bit_idx[0]); 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; 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) bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
{ {
assert(cp->bit_idx[1] > 0); assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0]; unsigned bit = cp->bit_idx[0];
if (bit >= 4) { unsigned wid = cp->bit_idx[1];
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);
}
} else { /* Make a vector of the desired width. */
unsigned char bit_val = strong_values[bit]; 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; return true;
} }
@ -2502,12 +2593,16 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
if ((unsigned)idx > cp->bit_idx[1]) if ((unsigned)idx > cp->bit_idx[1])
return true; return true;
#if 0
/* Form the functor pointer from the base pointer and the /* Form the functor pointer from the base pointer and the
index from the index register. */ index from the index register. */
vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx); vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx);
/* Set the value. */ /* Set the value. */
functor_set(itmp, bit_val, strong_values[bit_val], true); functor_set(itmp, bit_val, strong_values[bit_val], true);
#else
fprintf(stderr, "XXXX forgot how to implement %%set/x0\n");
#endif
return true; return true;
} }
@ -2527,12 +2622,16 @@ bool of_SET_X0_X(vthread_t thr, vvp_code_t cp)
if (idx > lim) if (idx > lim)
return true; return true;
#if 0
/* Form the functor pointer from the base pointer and the /* Form the functor pointer from the base pointer and the
index from the index register. */ index from the index register. */
vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx); vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx);
/* Set the value. */ /* Set the value. */
functor_set(itmp, bit_val, strong_values[bit_val], true); 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; return true;
} }
@ -2727,19 +2826,25 @@ bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
return schedule_finished()? false : true; return schedule_finished()? false : true;
} }
/* /* %wait <label>;
* Implement the wait by locating the functor for the event, and * Implement the wait by locating the vvp_net_T for the event, and
* adding this thread to the threads list for the event. * 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) bool of_WAIT(vthread_t thr, vvp_code_t cp)
{ {
assert(! thr->waiting_for_event); assert(! thr->waiting_for_event);
thr->waiting_for_event = 1; 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); assert(ep);
/* Add this thread to the list in the event. */
thr->wait_next = ep->threads; thr->wait_next = ep->threads;
ep->threads = thr; ep->threads = thr;
/* Return false to suspend this thread. */
return false; return false;
} }
@ -2874,6 +2979,11 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
/* /*
* $Log: vthread.cc,v $ * $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 * Revision 1.122 2004/10/04 01:11:00 steve
* Clean up spurious trailing white space. * 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