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:
parent
6854660e18
commit
65e9b6be12
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.170 2004/12/11 02:31:25 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -104,8 +104,8 @@ distclean: clean
|
|||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
|
||||
|
||||
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
|
||||
|
|
|
|||
10
Statement.h
10
Statement.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $"
|
||||
#ident "$Id: Statement.h,v 1.41 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -36,6 +36,7 @@ class Design;
|
|||
class NetAssign_;
|
||||
class NetCAssign;
|
||||
class NetDeassign;
|
||||
class NetForce;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
|
|
@ -345,7 +346,7 @@ class PForce : public Statement {
|
|||
explicit PForce(PExpr*l, PExpr*r);
|
||||
~PForce();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -456,6 +457,11 @@ class PWhile : public Statement {
|
|||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.41 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.40 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
115
cprop.cc
115
cprop.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.48 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -55,86 +55,6 @@ void cprop_functor::signal(Design*des, NetNet*obj)
|
|||
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
// For now, only additions are handled.
|
||||
if (obj->attribute(perm_string::literal("LPM_Direction")) != verinum("ADD"))
|
||||
return;
|
||||
|
||||
// If the low bit on the A side is 0, then eliminate it from
|
||||
// the adder, and pass the B side directly to the
|
||||
// result. Don't reduce the adder smaller then a 1-bit
|
||||
// adder. These will be eliminated later.
|
||||
while ((obj->width() > 1)
|
||||
&& obj->pin_DataA(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataA(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// Now do the same thing on the B side.
|
||||
while ((obj->width() > 1)
|
||||
&& obj->pin_DataB(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataB(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataA(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// If the adder is only 1 bit wide, then replace it with the
|
||||
// simple logic gate.
|
||||
if (obj->width() == 1) {
|
||||
NetLogic*tmp;
|
||||
if (obj->pin_Cout().is_linked()) {
|
||||
tmp = new NetLogic(obj->scope(),
|
||||
obj->scope()->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(tmp->pin(0), obj->pin_Cout());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
des->add_node(tmp);
|
||||
}
|
||||
tmp = new NetLogic(obj->scope(), obj->name(), 3, NetLogic::XOR);
|
||||
connect(tmp->pin(0), obj->pin_Result(0));
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
|
|
@ -248,7 +168,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
|||
with a simple XOR gate. */
|
||||
if (top == 1) {
|
||||
NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
|
||||
NetLogic::XNOR);
|
||||
NetLogic::XNOR, 1);
|
||||
connect(tmp->pin(0), obj->pin_AEB());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
|
|
@ -449,12 +369,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
case NetLogic::AND:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
break;
|
||||
case NetLogic::NAND:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -480,7 +400,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
obj->type(), 1);
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
|
@ -597,12 +517,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
case NetLogic::OR:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
break;
|
||||
case NetLogic::NOR:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -627,7 +547,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
obj->type(), 1);
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
|
@ -766,11 +686,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
if (obj->type() == NetLogic::XOR)
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
else
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
|
|
@ -795,11 +715,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
if (obj->type() == NetLogic::XOR)
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
else
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
|
|
@ -821,7 +741,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
obj->type(), 1);
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
|
|
@ -873,7 +793,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
|||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1);
|
||||
3, NetLogic::BUFIF1, 1);
|
||||
|
||||
connect(obj->pin_Result(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
|
|
@ -906,7 +826,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
|||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0);
|
||||
3, NetLogic::BUFIF0, 1);
|
||||
|
||||
connect(obj->pin_Result(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
|
|
@ -1038,6 +958,11 @@ void cprop(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.48 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.47 2004/02/20 18:53:34 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.149 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.150 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -96,8 +96,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope()->name();
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") init=";
|
||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||
<< decay_time() << ") vector_width=" << vector_width()
|
||||
<< " pin_count=" << pin_count()
|
||||
<< " init=";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << pin(idx-1).get_init();
|
||||
|
||||
|
|
@ -189,18 +191,13 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
|
|||
|
||||
void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
|
||||
<< " width=" << width() << " pin_count=" << pin_count()
|
||||
<< endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCAssign::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
|
|
@ -223,12 +220,6 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetForce::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force " << lval_->name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
|
||||
|
|
@ -249,7 +240,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
|||
o << setw(ind) << "" << "NetBUFZ: " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ")" << endl;
|
||||
decay_time() << ") width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
|
|
@ -261,8 +252,8 @@ void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
|||
|
||||
void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant ";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << setw(ind) << "" << "constant " << width_ << "'b";
|
||||
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
|
|
@ -353,6 +344,13 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetPartSelect: "
|
||||
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
|
|
@ -557,8 +555,9 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetCAssign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "cassign " << lval_->name() << " = "
|
||||
<< name() << ";" << endl;
|
||||
o << setw(ind) << "" << "cassign ";
|
||||
dump_lval(o);
|
||||
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -578,8 +577,9 @@ void NetCondit::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "deassign " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "deassign ";
|
||||
dump_lval(o);
|
||||
o << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetDisable::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -632,8 +632,9 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetForce::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force " << lval_->name() << " = "
|
||||
<< name() << ";" << endl;
|
||||
o << setw(ind) << "" << "force ";
|
||||
dump_lval(o);
|
||||
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetForever::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -677,12 +678,9 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetRelease::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (lval_)
|
||||
o << setw(ind) << "" << "release " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "release (null); "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "release ";
|
||||
dump_lval(o);
|
||||
o << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -995,7 +993,7 @@ void NetESignal::dump(ostream&o) const
|
|||
{
|
||||
if (has_sign())
|
||||
o << "+";
|
||||
o << name() << "[" << msi_<<":"<<lsi_ << "]";
|
||||
o << name() << "[" << msi()<<":"<<lsi() << "]";
|
||||
}
|
||||
|
||||
void NetEBitSel::dump(ostream&o) const
|
||||
|
|
@ -1089,6 +1087,11 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.150 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.149 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.18 2004/06/17 16:06:18 steve Exp $"
|
||||
#ident "$Id: dup_expr.cc,v 1.19 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -87,7 +87,7 @@ NetESFunc* NetESFunc::dup_expr() const
|
|||
|
||||
NetESignal* NetESignal::dup_expr() const
|
||||
{
|
||||
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
|
||||
NetESignal*tmp = new NetESignal(net_);
|
||||
assert(tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
return tmp;
|
||||
|
|
@ -143,6 +143,11 @@ NetEVariable* NetEVariable::dup_expr() const
|
|||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.19 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
|
|
|||
20
elab_expr.cc
20
elab_expr.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.91 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.92 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -699,10 +699,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
NetESignal*tmp = new NetESignal(net,
|
||||
net->sb_to_idx(msv),
|
||||
net->sb_to_idx(lsv));
|
||||
#else
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
cerr << get_line() << ": internal error: I forgot "
|
||||
"how to elaborate part selects." << endl;
|
||||
#endif
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
|
|
@ -735,7 +740,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
#if 0
|
||||
NetESignal*tmp = new NetESignal(net, idx, idx);
|
||||
#else
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
cerr << get_line() << ": internal error: I forgot "
|
||||
"how to elaborate constant bit selects." << endl;
|
||||
#endif
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
|
|
@ -1005,6 +1016,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.92 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.91 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
11
elab_lval.cc
11
elab_lval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.30 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -283,7 +283,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
|||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->pin_count()) {
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_line() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
|
|
@ -293,8 +293,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
|||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(loff, wid);
|
||||
|
||||
assert(moff < reg->pin_count());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -352,6 +350,11 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
|||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.30 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.29 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
200
elab_net.cc
200
elab_net.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.138 2004/10/04 03:09:38 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.139 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -195,14 +195,13 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
|
|||
/* The owidth is the output width of the lpm_add_sub
|
||||
device. If the desired width is greater then the width of
|
||||
the operands, then widen the adder and let code below pad
|
||||
the operands. If this is an adder, we can take advantage of
|
||||
the carry bit. */
|
||||
the operands. */
|
||||
unsigned owidth = width;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
if (lwidth > owidth) {
|
||||
owidth = lwidth;
|
||||
width = lwidth-1;
|
||||
width = lwidth;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
|
|
@ -228,18 +227,21 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
|
|||
osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, owidth);
|
||||
osig->local_flag(true);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate NetAddSub "
|
||||
<< "width=" << width << " lwidth=" << lwidth
|
||||
<< endl;
|
||||
}
|
||||
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), width);
|
||||
|
||||
// Connect the adder to the various parts.
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(lsig->pin(idx), adder->pin_DataA(idx));
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(rsig->pin(idx), adder->pin_DataB(idx));
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(osig->pin(idx), adder->pin_Result(idx));
|
||||
connect(lsig->pin(0), adder->pin_DataA());
|
||||
connect(rsig->pin(0), adder->pin_DataB());
|
||||
connect(osig->pin(0), adder->pin_Result());
|
||||
#ifdef XXXX
|
||||
if (owidth > width)
|
||||
connect(osig->pin(width), adder->pin_Cout());
|
||||
|
||||
#endif
|
||||
NetNode*gate = adder;
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
|
|
@ -311,7 +313,7 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
|
|||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, gtype);
|
||||
3, gtype, 1);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
|
|
@ -394,12 +396,12 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
|
|||
NetLogic*ones_gate = 0;
|
||||
if (zeros > 0)
|
||||
zero_gate = new NetLogic(scope,
|
||||
scope->local_symbol(), zeros + 1,
|
||||
(op_code == 'n') ? NetLogic::OR : NetLogic::NOR);
|
||||
scope->local_symbol(), zeros + 1,
|
||||
(op_code == 'n') ? NetLogic::OR : NetLogic::NOR, 1);
|
||||
if (ones > 0)
|
||||
ones_gate = new NetLogic(scope,
|
||||
scope->local_symbol(), ones + 1,
|
||||
(op_code == 'n') ? NetLogic::NAND : NetLogic::AND);
|
||||
scope->local_symbol(), ones + 1,
|
||||
(op_code == 'n') ? NetLogic::NAND : NetLogic::AND, 1);
|
||||
|
||||
unsigned zidx = 0;
|
||||
unsigned oidx = 0;
|
||||
|
|
@ -426,7 +428,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
|
|||
connect(and_sig->pin(1), ones_gate->pin(0));
|
||||
NetLogic*and_gate = new NetLogic(scope,
|
||||
scope->local_symbol(), 3,
|
||||
(op_code == 'n') ? NetLogic::OR : NetLogic::AND);
|
||||
(op_code == 'n') ? NetLogic::OR : NetLogic::AND, 1);
|
||||
connect(and_gate->pin(0), osig->pin(0));
|
||||
connect(and_gate->pin(1), and_sig->pin(0));
|
||||
connect(and_gate->pin(2), and_sig->pin(1));
|
||||
|
|
@ -625,7 +627,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
1+dwidth,
|
||||
(op_ == 'E')? NetLogic::AND : NetLogic::NAND);
|
||||
(op_ == 'E')? NetLogic::AND : NetLogic::NAND, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
NetCaseCmp*cmp = new NetCaseCmp(scope,
|
||||
|
|
@ -659,7 +661,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
single XNOR gate. This is easy and direct. */
|
||||
if (dwidth == 1) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR);
|
||||
3, NetLogic::XNOR, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
|
|
@ -693,7 +695,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
single XOR gate. This is easy and direct. */
|
||||
if (dwidth == 1) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR);
|
||||
3, NetLogic::XOR, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
|
|
@ -899,11 +901,11 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
|||
switch (op_) {
|
||||
case 'a':
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
3, NetLogic::AND, 1);
|
||||
break;
|
||||
case 'o':
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
3, NetLogic::OR, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -915,7 +917,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
|||
// The first OR gate returns 1 if the left value is true...
|
||||
if (lsig->pin_count() > 1) {
|
||||
gate_t = new NetLogic(scope, scope->local_symbol(),
|
||||
1+lsig->pin_count(), NetLogic::OR);
|
||||
1+lsig->pin_count(), NetLogic::OR, 1);
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(gate_t->pin(idx+1), lsig->pin(idx));
|
||||
|
||||
|
|
@ -937,7 +939,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
|||
// The second OR gate returns 1 if the right value is true...
|
||||
if (rsig->pin_count() > 1) {
|
||||
gate_t = new NetLogic(scope, scope->local_symbol(),
|
||||
1+rsig->pin_count(), NetLogic::OR);
|
||||
1+rsig->pin_count(), NetLogic::OR, 1);
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(gate_t->pin(idx+1), rsig->pin(idx));
|
||||
connect(gate->pin(2), gate_t->pin(0));
|
||||
|
|
@ -1586,7 +1588,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
signal for the part select to be correct. */
|
||||
if (! (sig->sb_is_valid(mbit) && sig->sb_is_valid(lbit))) {
|
||||
cerr << get_line() << ": error: bit/part select ["
|
||||
<< mval->as_long() << ":" << lval->as_long()
|
||||
<< mbit << ":" << lbit
|
||||
<< "] out of range for " << sig->name() << endl;
|
||||
des->errors += 1;
|
||||
return sig;
|
||||
|
|
@ -1619,7 +1621,19 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
unsigned part_count = midx-lidx+1;
|
||||
|
||||
NetSubnet*tmp = new NetSubnet(sig, lidx, part_count);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part select "
|
||||
<< sig->name() << "["<<mbit<<":"<<lbit<<"]" << endl;
|
||||
}
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count);
|
||||
ps->set_line(*sig);
|
||||
des->add_node(ps);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, part_count-1, 0);
|
||||
tmp->local_flag(true);
|
||||
connect(tmp->pin(0), ps->pin(0));
|
||||
|
||||
sig = tmp;
|
||||
|
||||
|
|
@ -1632,15 +1646,35 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
assert(mval);
|
||||
unsigned idx = sig->sb_to_idx(mval->as_long());
|
||||
if (idx >= sig->pin_count()) {
|
||||
cerr << get_line() << ": error: index " << sig->name() <<
|
||||
"[" << mval->as_long() << "] out of range." << endl;
|
||||
long mbit = mval->as_long();
|
||||
|
||||
/* Check that the part select is valid. Both ends of the
|
||||
constant part select must be within the range of the
|
||||
signal for the part select to be correct. */
|
||||
if (! sig->sb_is_valid(mbit)) {
|
||||
cerr << get_line() << ": error: bit/part select ["
|
||||
<< mbit
|
||||
<< "] out of range for " << sig->name() << endl;
|
||||
des->errors += 1;
|
||||
idx = 0;
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
|
||||
unsigned midx = sig->sb_to_idx(mbit);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part select "
|
||||
<< sig->name() << "["<<mval->as_long()<<"]" << endl;
|
||||
}
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(sig, midx, 1);
|
||||
ps->set_line(*sig);
|
||||
des->add_node(ps);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1, 0);
|
||||
tmp->local_flag(true);
|
||||
connect(tmp->pin(0), ps->pin(0));
|
||||
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -1698,7 +1732,10 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value.
|
||||
* it as a structural l-value. The return values is the *input* net of
|
||||
* the l-value, which may feed via part selects to the final
|
||||
* destination. The caller can connect gate outputs to this signal to
|
||||
* make the l-value connections.
|
||||
*/
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
|
|
@ -1706,7 +1743,7 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
|||
assert(scope);
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned width = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
if (repeat_) {
|
||||
|
|
@ -1718,6 +1755,12 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
|||
/* Elaborate the operands of the concatenation. */
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate subexpression "
|
||||
<< idx << " of " << nets.count() << " l-values: "
|
||||
<< *parms_[idx] << endl;
|
||||
}
|
||||
|
||||
if (parms_[idx] == 0) {
|
||||
cerr << get_line() << ": error: Empty expressions "
|
||||
<< "not allowed in concatenations." << endl;
|
||||
|
|
@ -1730,7 +1773,7 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
|||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
width += nets[idx]->vector_width();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
|
|
@ -1745,19 +1788,33 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
|||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list. */
|
||||
concat operator from most significant to least significant,
|
||||
which is the order they are given in the concat list. */
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, pins);
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
NetNet::IMPLICIT, width);
|
||||
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Generating part selects "
|
||||
<< "to connect input l-value to subexpressions."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
unsigned wid = nets[idx]->vector_width();
|
||||
unsigned off = width - wid;
|
||||
NetPartSelect*ps = new NetPartSelect(osig, off, wid);
|
||||
des->add_node(ps);
|
||||
|
||||
connect(ps->pin(1), osig->pin(0));
|
||||
connect(ps->pin(0), nets[idx]->pin(0));
|
||||
|
||||
assert(wid <= width);
|
||||
width -= wid;
|
||||
}
|
||||
assert(width == 0);
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
|
@ -2046,18 +2103,15 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
|
|||
break;
|
||||
}
|
||||
|
||||
verinum num(top_v, net->pin_count());
|
||||
verinum num(top_v, net->vector_width());
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1)
|
||||
num.set(idx, value_->get(idx));
|
||||
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
|
||||
num);
|
||||
for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
tmp->pin(idx).drive0(drive0);
|
||||
tmp->pin(idx).drive1(drive1);
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
}
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
|
||||
tmp->pin(0).drive0(drive0);
|
||||
tmp->pin(0).drive1(drive1);
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
|
||||
des->add_node(tmp);
|
||||
return net;
|
||||
|
|
@ -2073,8 +2127,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
|
|||
net->set_signed(value_->has_sign());
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
|
||||
*value_);
|
||||
for (unsigned idx = 0 ; idx < value_->len() ; idx += 1)
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
|
||||
des->add_node(tmp);
|
||||
return net;
|
||||
|
|
@ -2116,8 +2169,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
|
|||
NetNet::IMPLICIT, width);
|
||||
net->local_flag(true);
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
|
||||
des->add_node(tmp);
|
||||
return net;
|
||||
|
|
@ -2224,7 +2276,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
if (expr_sig->pin_count() > 1) {
|
||||
NetLogic*log = new NetLogic(scope, scope->local_symbol(),
|
||||
expr_sig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
NetLogic::OR, 1);
|
||||
for (unsigned idx = 0; idx < expr_sig->pin_count(); idx += 1)
|
||||
connect(log->pin(idx+1), expr_sig->pin(idx));
|
||||
|
||||
|
|
@ -2284,7 +2336,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
NetNet::WIRE, dwidth);
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol());
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(), 1);
|
||||
tmpz->rise_time(rise);
|
||||
tmpz->fall_time(fall);
|
||||
tmpz->decay_time(decay);
|
||||
|
|
@ -2388,7 +2440,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
sig->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
2, NetLogic::NOT, 1);
|
||||
connect(gate->pin(1), sub_sig->pin(idx));
|
||||
connect(gate->pin(0), sig->pin(idx));
|
||||
des->add_node(gate);
|
||||
|
|
@ -2427,7 +2479,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
case 1:
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
2, NetLogic::BUF);
|
||||
2, NetLogic::BUF, 1);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
connect(gate->pin(1), sub_sig->pin(0));
|
||||
des->add_node(gate);
|
||||
|
|
@ -2438,7 +2490,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
case 2:
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
2, NetLogic::BUF);
|
||||
2, NetLogic::BUF, 1);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
connect(gate->pin(1), sub_sig->pin(0));
|
||||
des->add_node(gate);
|
||||
|
|
@ -2447,7 +2499,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
gate->decay_time(decay);
|
||||
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR);
|
||||
3, NetLogic::XOR, 1);
|
||||
connect(gate->pin(0), sig->pin(1));
|
||||
connect(gate->pin(1), sub_sig->pin(0));
|
||||
connect(gate->pin(2), sub_sig->pin(1));
|
||||
|
|
@ -2464,11 +2516,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
des->add_node(sub);
|
||||
|
||||
for (unsigned idx = 0 ; idx < sig->pin_count(); idx += 1)
|
||||
connect(sig->pin(idx), sub->pin_Result(idx));
|
||||
|
||||
for (unsigned idx = 0; idx < sub_sig->pin_count(); idx += 1)
|
||||
connect(sub_sig->pin(idx), sub->pin_DataB(idx));
|
||||
connect(sig->pin(0), sub->pin_Result());
|
||||
connect(sub_sig->pin(0), sub->pin_DataB());
|
||||
|
||||
verinum tmp_num (verinum::V0, sub->width(), true);
|
||||
NetConst*tmp_con = new NetConst(scope,
|
||||
|
|
@ -2481,10 +2530,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
sub_sig->pin_count());
|
||||
tmp_sig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
|
||||
connect(tmp_sig->pin(idx), sub->pin_DataA(idx));
|
||||
connect(tmp_sig->pin(idx), tmp_con->pin(idx));
|
||||
}
|
||||
connect(tmp_sig->pin(0), sub->pin_DataA());
|
||||
connect(tmp_sig->pin(0), tmp_con->pin(0));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -2497,7 +2544,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
|
||||
sig->local_flag(true);
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
1+sub_sig->pin_count(), gtype);
|
||||
1+sub_sig->pin_count(), gtype, 1);
|
||||
connect(gate->pin(0), sig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), sub_sig->pin(idx));
|
||||
|
|
@ -2513,6 +2560,11 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.139 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.138 2004/10/04 03:09:38 steve
|
||||
* Fix excessive error message.
|
||||
*
|
||||
|
|
|
|||
13
elab_sig.cc
13
elab_sig.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_sig.cc,v 1.36 2004/09/27 22:34:10 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.37 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -610,6 +610,12 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
} else {
|
||||
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Create signal "
|
||||
<< name << "["<<msb<<":"<<lsb<<"]"
|
||||
<< " in scope " << scope->name() << endl;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
|
|
@ -623,6 +629,11 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.37 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.36 2004/09/27 22:34:10 steve
|
||||
* Cleanup and factoring of autoconf.
|
||||
*
|
||||
|
|
|
|||
294
elaborate.cc
294
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.308 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.309 2004/12/11 02:31:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -91,6 +91,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
return;
|
||||
}
|
||||
|
||||
assert(lval->pin_count() == 1);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << lval->get_line() << ": debug: Elaborated l-value "
|
||||
<< "width=" << lval->vector_width() << endl;
|
||||
}
|
||||
|
||||
/* Handle the special case that the rval is simply an
|
||||
identifier. Get the rval as a NetNet, then use NetBUFZ
|
||||
|
|
@ -98,7 +104,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
direct drivers. This is how I attach strengths to the
|
||||
assignment operation. */
|
||||
if (const PEIdent*id = dynamic_cast<const PEIdent*>(pin(1))) {
|
||||
NetNet*rid = id->elaborate_net(des, scope, lval->pin_count(),
|
||||
NetNet*rid = id->elaborate_net(des, scope, lval->vector_width(),
|
||||
0, 0, 0, Link::STRONG,
|
||||
Link::STRONG);
|
||||
if (rid == 0) {
|
||||
|
|
@ -107,7 +113,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
assert(rid);
|
||||
|
||||
assert(rid->pin_count() == 1);
|
||||
|
||||
/* If the right hand net is the same type as the left
|
||||
side net (i.e., WIRE/WIRE) then it is enough to just
|
||||
|
|
@ -118,20 +124,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
is not as wide as the l-value by padding with a
|
||||
constant-0. */
|
||||
|
||||
unsigned cnt = lval->pin_count();
|
||||
if (rid->pin_count() < cnt)
|
||||
unsigned cnt = lval->vector_width();
|
||||
if (rid->vector_width() < cnt)
|
||||
cnt = rid->pin_count();
|
||||
|
||||
bool need_driver_flag = false;
|
||||
|
||||
/* If the device is linked to itself, a driver is
|
||||
needed. Should I print a warning here? */
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
if (lval->pin(idx) .is_linked (rid->pin(idx))) {
|
||||
need_driver_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lval->pin(0) .is_linked (rid->pin(0)))
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If the nets are different type (i.e., reg vs. tri) then
|
||||
a driver is needed. */
|
||||
|
|
@ -145,16 +147,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* If there is a strength to be carried, then I need a
|
||||
driver to carry that strength. */
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
if (rid->pin(idx).drive0() != drive0) {
|
||||
need_driver_flag = true;
|
||||
break;
|
||||
}
|
||||
if (rid->pin(idx).drive1() != drive1) {
|
||||
need_driver_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rid->pin(0).drive0() != drive0)
|
||||
need_driver_flag = true;
|
||||
|
||||
if (rid->pin(0).drive1() != drive1)
|
||||
need_driver_flag = true;
|
||||
|
||||
|
||||
if (! need_driver_flag) {
|
||||
/* Don't need a driver, presumably because the
|
||||
|
|
@ -162,11 +160,10 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
hook things up. If the r-value is too narrow
|
||||
for the l-value, then sign extend it or zero
|
||||
extend it, whichever makes sense. */
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt; idx += 1)
|
||||
connect(lval->pin(idx), rid->pin(idx));
|
||||
connect(lval->pin(0), rid->pin(0));
|
||||
|
||||
if (cnt < lval->pin_count()) {
|
||||
#if 0
|
||||
if (lval->get_signed() && rid->get_signed()) {
|
||||
for (idx = cnt
|
||||
; idx < lval->pin_count()
|
||||
|
|
@ -184,45 +181,28 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
; idx += 1)
|
||||
connect(lval->pin(idx), tmp->pin(idx-cnt));
|
||||
}
|
||||
#else
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Forgot how to handle mismatched widths."
|
||||
<< endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Do need a driver. Use BUFZ objects to carry the
|
||||
strength and delays. */
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
NetBUFZ*dev = new NetBUFZ(scope,scope->local_symbol());
|
||||
connect(lval->pin(idx), dev->pin(0));
|
||||
connect(rid->pin(idx), dev->pin(1));
|
||||
dev->rise_time(rise_time);
|
||||
dev->fall_time(fall_time);
|
||||
dev->decay_time(decay_time);
|
||||
dev->pin(0).drive0(drive0);
|
||||
dev->pin(0).drive1(drive1);
|
||||
des->add_node(dev);
|
||||
}
|
||||
|
||||
if (cnt < lval->pin_count()) {
|
||||
if (lval->get_signed() && rid->get_signed()) {
|
||||
for (idx = cnt
|
||||
; idx < lval->pin_count()
|
||||
; idx += 1)
|
||||
connect(lval->pin(idx), lval->pin(cnt-1));
|
||||
NetBUFZ*dev = new NetBUFZ(scope, scope->local_symbol(),
|
||||
rid->vector_width());
|
||||
connect(lval->pin(0), dev->pin(0));
|
||||
connect(rid->pin(0), dev->pin(1));
|
||||
dev->rise_time(rise_time);
|
||||
dev->fall_time(fall_time);
|
||||
dev->decay_time(decay_time);
|
||||
dev->pin(0).drive0(drive0);
|
||||
dev->pin(0).drive1(drive1);
|
||||
des->add_node(dev);
|
||||
|
||||
} else {
|
||||
NetConst*dev = new NetConst(scope,
|
||||
scope->local_symbol(),
|
||||
verinum::V0);
|
||||
|
||||
des->add_node(dev);
|
||||
dev->pin(0).drive0(drive0);
|
||||
dev->pin(0).drive1(drive1);
|
||||
for (idx = cnt
|
||||
; idx < lval->pin_count()
|
||||
; idx += 1)
|
||||
connect(lval->pin(idx), dev->pin(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -232,7 +212,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
which are going to be attached to the last gate before the
|
||||
generated NetNet. */
|
||||
NetNet*rval = pin(1)->elaborate_net(des, scope,
|
||||
lval->pin_count(),
|
||||
lval->vector_width(),
|
||||
rise_time, fall_time, decay_time,
|
||||
drive0, drive1);
|
||||
if (rval == 0) {
|
||||
|
|
@ -243,17 +223,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
assert(lval && rval);
|
||||
|
||||
assert(rval->pin_count() == 1);
|
||||
|
||||
/* If the r-value insists on being smaller then the l-value
|
||||
(perhaps it is explicitly sized) the pad it out to be the
|
||||
right width so that something is connected to all the bits
|
||||
of the l-value. */
|
||||
if (lval->pin_count() > rval->pin_count())
|
||||
rval = pad_to_width(des, rval, lval->pin_count());
|
||||
if (lval->vector_width() > rval->vector_width())
|
||||
rval = pad_to_width(des, rval, lval->vector_width());
|
||||
|
||||
for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1)
|
||||
connect(lval->pin(idx), rval->pin(idx));
|
||||
connect(lval->pin(0), rval->pin(0));
|
||||
|
||||
if (lval->local_flag())
|
||||
delete lval;
|
||||
|
|
@ -355,75 +334,75 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
switch (type()) {
|
||||
case AND:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::AND);
|
||||
NetLogic::AND, 1);
|
||||
break;
|
||||
case BUF:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
break;
|
||||
case BUFIF0:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF0);
|
||||
NetLogic::BUFIF0, 1);
|
||||
break;
|
||||
case BUFIF1:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF1);
|
||||
NetLogic::BUFIF1, 1);
|
||||
break;
|
||||
case NAND:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NAND);
|
||||
NetLogic::NAND, 1);
|
||||
break;
|
||||
case NMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NMOS);
|
||||
NetLogic::NMOS, 1);
|
||||
break;
|
||||
case NOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOR);
|
||||
NetLogic::NOR, 1);
|
||||
break;
|
||||
case NOT:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
break;
|
||||
case NOTIF0:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF0);
|
||||
NetLogic::NOTIF0, 1);
|
||||
break;
|
||||
case NOTIF1:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF1);
|
||||
NetLogic::NOTIF1, 1);
|
||||
break;
|
||||
case OR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::OR);
|
||||
NetLogic::OR, 1);
|
||||
break;
|
||||
case RNMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RNMOS);
|
||||
NetLogic::RNMOS, 1);
|
||||
break;
|
||||
case RPMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RPMOS);
|
||||
NetLogic::RPMOS, 1);
|
||||
break;
|
||||
case PMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PMOS);
|
||||
NetLogic::PMOS, 1);
|
||||
break;
|
||||
case PULLDOWN:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLDOWN);
|
||||
NetLogic::PULLDOWN, 1);
|
||||
break;
|
||||
case PULLUP:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLUP);
|
||||
NetLogic::PULLUP, 1);
|
||||
break;
|
||||
case XNOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XNOR);
|
||||
NetLogic::XNOR, 1);
|
||||
break;
|
||||
case XOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XOR);
|
||||
NetLogic::XOR, 1);
|
||||
break;
|
||||
default:
|
||||
cerr << get_line() << ": internal error: unhandled "
|
||||
|
|
@ -1712,29 +1691,36 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
return block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate a proceedural continuous assign. This really looks very
|
||||
* much like other prodeedural assignments, at this point, but there
|
||||
* is no delay to worry about. The code generator will take care of
|
||||
* the differences between continuous assign and normal assignments.
|
||||
*/
|
||||
NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetCAssign*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
NetNet*lval = lval_->elaborate_anet(des, scope);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
NetNet*rval = expr_->elaborate_net(des, scope, lval->pin_count(),
|
||||
0, 0, 0);
|
||||
if (rval == 0)
|
||||
NetExpr*rexp = elab_and_eval(des, scope, expr_);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
if (rval->pin_count() < lval->pin_count())
|
||||
rval = pad_to_width(des, rval, lval->pin_count());
|
||||
dev = new NetCAssign(lval, rexp);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: ELaborate cassign,"
|
||||
<< " lval width=" << lval->lwidth()
|
||||
<< " rval width=" << rexp->expr_width()
|
||||
<< " rval=" << *rexp
|
||||
<< endl;
|
||||
}
|
||||
|
||||
NetCAssign* dev = new NetCAssign(scope, scope->local_symbol(), lval);
|
||||
dev->set_line(*this);
|
||||
des->add_node(dev);
|
||||
|
||||
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1)
|
||||
connect(dev->pin(idx), rval->pin(idx));
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
|
@ -1742,7 +1728,7 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
NetNet*lval = lval_->elaborate_anet(des, scope);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -2225,28 +2211,30 @@ NetProc* PForever::elaborate(Design*des, NetScope*scope) const
|
|||
return proc;
|
||||
}
|
||||
|
||||
NetProc* PForce::elaborate(Design*des, NetScope*scope) const
|
||||
NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetForce*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
NetNet*rval = expr_->elaborate_net(des, scope, lval->pin_count(),
|
||||
0, 0, 0);
|
||||
if (rval == 0)
|
||||
NetExpr*rexp = elab_and_eval(des, scope, expr_);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
if (rval->pin_count() < lval->pin_count())
|
||||
rval = pad_to_width(des, rval, lval->pin_count());
|
||||
dev = new NetForce(lval, rexp);
|
||||
|
||||
NetForce* dev = new NetForce(scope, scope->local_symbol(), lval);
|
||||
des->add_node(dev);
|
||||
|
||||
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1)
|
||||
connect(dev->pin(idx), rval->pin(idx));
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: ELaborate force,"
|
||||
<< " lval width=" << lval->lwidth()
|
||||
<< " rval width=" << rexp->expr_width()
|
||||
<< " rval=" << *rexp
|
||||
<< endl;
|
||||
}
|
||||
|
||||
dev->set_line(*this);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
|
@ -2398,7 +2386,7 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -2769,96 +2757,10 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.308 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
* Revision 1.309 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.307 2004/09/05 21:07:26 steve
|
||||
* Support degenerat wait statements.
|
||||
*
|
||||
* Revision 1.306 2004/09/05 17:44:41 steve
|
||||
* Add support for module instance arrays.
|
||||
*
|
||||
* Revision 1.305 2004/06/30 15:32:02 steve
|
||||
* Propagate source line number in synthetic delay statements.
|
||||
*
|
||||
* Revision 1.304 2004/06/20 15:59:06 steve
|
||||
* Only pad the width of vector r-values.
|
||||
*
|
||||
* Revision 1.303 2004/06/13 04:56:54 steve
|
||||
* Add support for the default_nettype directive.
|
||||
*
|
||||
* Revision 1.302 2004/05/31 23:34:37 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.301 2004/05/25 03:42:58 steve
|
||||
* Handle wait with constant-false expression.
|
||||
*
|
||||
* Revision 1.300 2004/03/08 00:47:44 steve
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
* Revision 1.299 2004/03/08 00:10:29 steve
|
||||
* Verilog2001 new style port declartions for primitives.
|
||||
*
|
||||
* Revision 1.298 2004/03/07 20:04:10 steve
|
||||
* MOre thorough use of elab_and_eval function.
|
||||
*
|
||||
* Revision 1.297 2004/02/20 18:53:34 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.296 2004/02/18 17:11:55 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.295 2004/01/21 04:35:03 steve
|
||||
* Get rid of useless warning.
|
||||
*
|
||||
* Revision 1.294 2004/01/13 03:42:49 steve
|
||||
* Handle wide expressions in wait condition.
|
||||
*
|
||||
* Revision 1.293 2003/10/26 04:49:51 steve
|
||||
* Attach line number information to for loop parts.
|
||||
*
|
||||
* Revision 1.292 2003/09/25 00:25:14 steve
|
||||
* Summary list of missing modules.
|
||||
*
|
||||
* Revision 1.291 2003/09/20 06:08:53 steve
|
||||
* Evaluate nb-assign r-values using elab_and_eval.
|
||||
*
|
||||
* Revision 1.290 2003/09/20 06:00:37 steve
|
||||
* Evaluate gate array index constants using elab_and_eval.
|
||||
*
|
||||
* Revision 1.289 2003/09/20 01:05:35 steve
|
||||
* Obsolete find_symbol and find_event from the Design class.
|
||||
*
|
||||
* Revision 1.288 2003/09/13 01:01:51 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.287 2003/09/04 20:28:05 steve
|
||||
* Support time0 resolution of combinational threads.
|
||||
*
|
||||
* Revision 1.286 2003/08/28 04:11:17 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
* Revision 1.285 2003/08/05 03:01:58 steve
|
||||
* Primitive outputs have same limitations as continuous assignment.
|
||||
*
|
||||
* Revision 1.284 2003/07/02 04:19:16 steve
|
||||
* Elide empty begin-end in conditionals.
|
||||
*
|
||||
* Revision 1.283 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
* Revision 1.282 2003/06/13 19:10:20 steve
|
||||
* Handle assign of real to vector.
|
||||
*
|
||||
* Revision 1.281 2003/05/19 02:50:58 steve
|
||||
* Implement the wait statement behaviorally instead of as nets.
|
||||
*
|
||||
* Revision 1.280 2003/05/04 20:04:08 steve
|
||||
* Fix truncation of signed constant in constant addition.
|
||||
*
|
||||
* Revision 1.279 2003/04/24 05:25:55 steve
|
||||
* Include port name in port assignment error message.
|
||||
*/
|
||||
|
||||
|
|
|
|||
150
emit.cc
150
emit.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.77 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.78 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -63,12 +63,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetCAssign::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_cassign(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(this);
|
||||
|
|
@ -98,12 +92,6 @@ bool NetFF::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetForce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_force(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetModulo::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_modulo(this);
|
||||
|
|
@ -122,6 +110,11 @@ bool NetMux::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetPartSelect::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->part_select(this);
|
||||
}
|
||||
|
||||
bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ram_dq(this);
|
||||
|
|
@ -511,6 +504,11 @@ bool emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.78 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.77 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
@ -536,131 +534,5 @@ bool emit(const Design*des, const char*type)
|
|||
* Revision 1.71 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.70 2002/11/03 20:36:10 steve
|
||||
* Error message for mising code generator type.
|
||||
*
|
||||
* Revision 1.69 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.68 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.67 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.66 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.65 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.64 2002/01/19 19:02:08 steve
|
||||
* Pass back target errors processing conditionals.
|
||||
*
|
||||
* Revision 1.63 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.62 2001/08/25 23:50:02 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.61 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.60 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.59 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.58 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.57 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.56 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.55 2000/11/04 01:54:01 steve
|
||||
* Modifications in support of gcc 2.96
|
||||
*
|
||||
* Revision 1.54 2000/09/26 01:35:42 steve
|
||||
* Remove the obsolete NetEIdent class.
|
||||
*
|
||||
* Revision 1.53 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.52 2000/09/02 20:54:20 steve
|
||||
* Rearrange NetAssign to make NetAssign_ separate.
|
||||
*
|
||||
* Revision 1.51 2000/08/14 04:39:56 steve
|
||||
* add th t-dll functions for net_const, net_bufz and processes.
|
||||
*
|
||||
* Revision 1.50 2000/08/09 03:43:45 steve
|
||||
* Move all file manipulation out of target class.
|
||||
*
|
||||
* Revision 1.49 2000/08/08 01:50:42 steve
|
||||
* target methods need not take a file stream.
|
||||
*
|
||||
* Revision 1.48 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.47 2000/07/29 16:21:08 steve
|
||||
* Report code generation errors through proc_delay.
|
||||
*
|
||||
* Revision 1.46 2000/07/27 05:13:44 steve
|
||||
* Support elaboration of disable statements.
|
||||
*
|
||||
* Revision 1.45 2000/05/11 23:37:27 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.44 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.43 2000/05/02 03:13:31 steve
|
||||
* Move memories to the NetScope object.
|
||||
*
|
||||
* Revision 1.42 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.41 2000/04/23 03:45:24 steve
|
||||
* Add support for the procedural release statement.
|
||||
*
|
||||
* Revision 1.40 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.39 2000/04/12 04:23:58 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.60 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -60,11 +60,9 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
|||
|
||||
perm_string oname = osig->scope()->local_symbol();
|
||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(lsig->pin(idx), adder->pin_DataA(idx));
|
||||
connect(rsig->pin(idx), adder->pin_DataB(idx));
|
||||
connect(osig->pin(idx), adder->pin_Result(idx));
|
||||
}
|
||||
connect(lsig->pin(0), adder->pin_DataA());
|
||||
connect(rsig->pin(0), adder->pin_DataB());
|
||||
connect(osig->pin(0), adder->pin_Result());
|
||||
des->add_node(adder);
|
||||
|
||||
switch (op()) {
|
||||
|
|
@ -136,19 +134,19 @@ NetNet* NetEBBits::synthesize(Design*des)
|
|||
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR, 1);
|
||||
break;
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, 1);
|
||||
break;
|
||||
case 'O':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, 1);
|
||||
break;
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -191,12 +189,12 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
case 'e':
|
||||
case 'E':
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
lsig->pin_count()+1, NetLogic::NOR, 1);
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
lsig->pin_count()+1, NetLogic::OR, 1);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
|
|
@ -205,11 +203,11 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
happen. */
|
||||
if (rcon) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
lsig->pin_count()+1, NetLogic::OR, 1);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
lsig->pin_count()+1, NetLogic::NOR, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -217,11 +215,11 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
/* 0 < sig is handled like sig > 0. */
|
||||
if (! rcon) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
lsig->pin_count()+1, NetLogic::OR, 1);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
lsig->pin_count()+1, NetLogic::NOR, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -258,7 +256,7 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
operation. Make an XNOR gate instead of a comparator. */
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR);
|
||||
3, NetLogic::XNOR, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
|
|
@ -271,7 +269,7 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
an XOR instead of an XNOR gate. */
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR);
|
||||
3, NetLogic::XOR, 1);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
|
|
@ -449,7 +447,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
|
||||
NetLogic*olog = new NetLogic(scope, oname,
|
||||
lsig->pin_count()+rsig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
NetLogic::OR, 1);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
|
||||
|
|
@ -471,7 +469,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
NetLogic*olog;
|
||||
perm_string oname = scope->local_symbol();
|
||||
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
des->add_node(olog);
|
||||
|
|
@ -669,7 +667,7 @@ NetNet* NetEUBits::synthesize(Design*des)
|
|||
|
||||
switch (op()) {
|
||||
case '~':
|
||||
gate = new NetLogic(scope, oname, 2, NetLogic::NOT);
|
||||
gate = new NetLogic(scope, oname, 2, NetLogic::NOT, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -702,32 +700,32 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
|||
case 'N':
|
||||
case '!':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NOR);
|
||||
NetLogic::NOR, 1);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::AND);
|
||||
NetLogic::AND, 1);
|
||||
break;
|
||||
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
NetLogic::OR, 1);
|
||||
break;
|
||||
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XOR);
|
||||
NetLogic::XOR, 1);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NAND);
|
||||
NetLogic::NAND, 1);
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XNOR);
|
||||
NetLogic::XNOR, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -854,27 +852,16 @@ NetNet* NetETernary::synthesize(Design *des)
|
|||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
|
||||
return net_;
|
||||
|
||||
assert(msi_ >= lsi_);
|
||||
unsigned wid = msi_ - lsi_ + 1;
|
||||
|
||||
NetScope*scope = net_->scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string name = scope->local_symbol();
|
||||
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net_->pin(idx+lsi_));
|
||||
|
||||
return tmp;
|
||||
return net_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.60 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.59 2004/06/30 02:16:26 steve
|
||||
* Implement signed divide and signed right shift in nets.
|
||||
*
|
||||
|
|
|
|||
1
ivl.def
1
ivl.def
|
|
@ -62,6 +62,7 @@ ivl_logic_udp
|
|||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_base
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
|
|
|
|||
112
ivl_target.h
112
ivl_target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.126 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.127 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -231,6 +231,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_MOD = 13,
|
||||
IVL_LPM_MULT = 4,
|
||||
IVL_LPM_MUX = 5,
|
||||
IVL_LPM_PART = 15, /* part select */
|
||||
IVL_LPM_SHIFTL = 6,
|
||||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SUB = 8,
|
||||
|
|
@ -388,13 +389,36 @@ extern int ivl_design_time_precision(ivl_design_t des);
|
|||
extern unsigned ivl_design_consts(ivl_design_t des);
|
||||
extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||
|
||||
/*
|
||||
* These methods apply to ivl_net_const_t objects.
|
||||
/* VECTOR CONSTANTS
|
||||
* Vector constants are nodes with no input and a single vector
|
||||
* output. The output is an array of 4-value bits, using a single char
|
||||
* value for each bit.
|
||||
*
|
||||
* ivl_const_bits
|
||||
* This returns a pointer to an array of conststant characters,
|
||||
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
|
||||
* terminated.
|
||||
*
|
||||
* ivl_const_nex
|
||||
* Return the ivl_nexus_t of the output for the constant.
|
||||
*
|
||||
* ivl_const_signed
|
||||
* Return true (!0) if the constant is a signed value, 0 otherwise.
|
||||
*
|
||||
* ivl_const_width
|
||||
* Return the width, in logical bits, of the constant.
|
||||
*
|
||||
* ivl_const_pin
|
||||
* ivl_const_pins
|
||||
* DEPRECATED
|
||||
*/
|
||||
extern const char* ivl_const_bits(ivl_net_const_t net);
|
||||
extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx);
|
||||
extern unsigned ivl_const_pins(ivl_net_const_t net);
|
||||
extern ivl_nexus_t ivl_const_nex(ivl_net_const_t net);
|
||||
extern int ivl_const_signed(ivl_net_const_t net);
|
||||
extern unsigned ivl_const_width(ivl_net_const_t net);
|
||||
|
||||
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
|
||||
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
|
||||
|
||||
/* EVENTS
|
||||
*
|
||||
|
|
@ -545,9 +569,13 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
|||
* the ivl_net_logic_t can represent. The various functions then
|
||||
* provide access to the bits of information for a given logic device.
|
||||
*
|
||||
* The ivl_net_logic_t nodes are bit-slice devices. That means that
|
||||
* the device may have width (and therefore processes vectors) but
|
||||
* each bit slice of the width is independent.
|
||||
*
|
||||
* ivl_logic_type
|
||||
* This method returns the type of logic gate that the cookie
|
||||
* represents.
|
||||
* This method returns the type of logic gate that the node
|
||||
* represents. The logic type implies the meaning of the various pins.
|
||||
*
|
||||
* ivl_logic_name (obsolete)
|
||||
* This method returns the complete name of the logic gate. Every
|
||||
|
|
@ -567,6 +595,11 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
|||
* together, then these values are the same. Use the nexus
|
||||
* functions to find other pins that are connected to this nexus.
|
||||
*
|
||||
* ivl_logic_width
|
||||
* This returns the width of the logic array. This does not affect
|
||||
* the number of pins, but implies the width of the vector at each
|
||||
* pin.
|
||||
*
|
||||
* ivl_logic_attr (obsolete)
|
||||
* Return the value of a specific attribute, given the key name as
|
||||
* a string. If the key is not defined, then return 0 (null).
|
||||
|
|
@ -633,6 +666,10 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* These functions apply to a subset of the LPM devices, or may have
|
||||
* varying meaning depending on the device:
|
||||
*
|
||||
* ivl_lpm_base
|
||||
* The IVL_LPM_PART objects use this value as the base (first bit)
|
||||
* of the part select. The ivl_lpm_width is the size of the part.
|
||||
*
|
||||
* ivl_lpm_data
|
||||
* Return the input data nexus for device types that have a single
|
||||
* input vector. This is also used to the get nexa of the first
|
||||
|
|
@ -674,13 +711,16 @@ extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
|
|||
extern ivl_nexus_t ivl_lpm_sync_clr(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT IVL_LPM_RAM
|
||||
IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_MUX IVL_LPM_UFUNC */
|
||||
|
|
@ -688,8 +728,8 @@ extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
|||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
|
|
@ -715,6 +755,11 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
* part select so that ivl_lval_pin(net, 0) is the proper bit in the
|
||||
* signal.
|
||||
*
|
||||
* ivl_lval_width
|
||||
* The width of a vector that this lval can receive. This accounts
|
||||
* for the local part selecting I might to in the lval object, as
|
||||
* well as the target object width.
|
||||
*
|
||||
* ivl_lval_mux
|
||||
* If the l-value includes a bit select expression, this method
|
||||
* returns an ivl_expr_t that represents that
|
||||
|
|
@ -751,14 +796,17 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
* Return the number of pins for this object.
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
|
||||
extern ivl_variable_t ivl_lval_var(ivl_lval_t net);
|
||||
extern unsigned ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
#if 0
|
||||
extern unsigned ivl_lval_pins(ivl_lval_t net);
|
||||
extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
#endif
|
||||
|
||||
/* NEXUS
|
||||
* connections of signals and nodes is handled by single-bit
|
||||
|
|
@ -1024,14 +1072,21 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
|||
* Signals have a name (obviously) and types. A signal may also be
|
||||
* signed or unsigned.
|
||||
*
|
||||
* ivl_signal_pins
|
||||
* ivl_signal_pins (replace these with ivl_signal_nex)
|
||||
* ivl_signal_pin
|
||||
* The ivl_signal_pin function returns the nexus connected to the
|
||||
* signal. If the signal is a vector, the idx can be a non-zero
|
||||
* value, and the result is the nexus for the specified bit.
|
||||
*
|
||||
* ivl_signal_nex
|
||||
* This is the nexus of the signal. This is used for managing
|
||||
* connections to the rest of the net. There is exactly one pin for
|
||||
* a signal. If the signal represents a vector, then the entire
|
||||
* vector is carried through the single output.
|
||||
*
|
||||
* ivl_signal_msb
|
||||
* ivl_signal_lsb
|
||||
* ivl_signal_width
|
||||
* These functions return the left and right indices, respectively,
|
||||
* of the signal. If the signal is a scalar, both return 0. However,
|
||||
* it doesn't mean that the signal is a scalar if both return 0, one
|
||||
|
|
@ -1077,10 +1132,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
|||
* key does not exist, the function returns 0.
|
||||
*/
|
||||
|
||||
extern ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx);
|
||||
extern unsigned ivl_signal_pins(ivl_signal_t net);
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net);
|
||||
extern int ivl_signal_msb(ivl_signal_t net);
|
||||
extern int ivl_signal_lsb(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_width(ivl_signal_t net);
|
||||
extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
|
||||
extern int ivl_signal_signed(ivl_signal_t net);
|
||||
extern int ivl_signal_integer(ivl_signal_t net);
|
||||
|
|
@ -1093,6 +1148,8 @@ extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
|
|||
extern unsigned ivl_signal_attr_cnt(ivl_signal_t net);
|
||||
extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
|
||||
|
||||
/* ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx); */
|
||||
/* unsigned ivl_signal_pins(ivl_signal_t net); */
|
||||
|
||||
/*
|
||||
* These functions get information about a process. A process is
|
||||
|
|
@ -1141,10 +1198,32 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
|||
* one type of statement, so the comment in front of them tells which
|
||||
* statement types can be passed to the function.
|
||||
*
|
||||
* FUNCTION SUMMARY:
|
||||
*
|
||||
* ivl_stmt_block_scope
|
||||
* If the block is named, then there is a scope associated with
|
||||
* this. The code generator may need to know this in order to
|
||||
* handle disable statements.
|
||||
*
|
||||
* ivl_stmt_rval
|
||||
* Return the rval expression of the assignment. This is the value
|
||||
* that is to be calculated and assigned to the l-value is
|
||||
* assignment statements.
|
||||
*
|
||||
* SOME INTERESTING SPECIAL CASES:
|
||||
*
|
||||
* - IVL_ST_CASSIGN
|
||||
* This reflects a procedural continuous assignment to an l-value. The
|
||||
* l-value is the same as any other assignment (use ivl_stmt_lval).
|
||||
*
|
||||
* The value to be assigned may be an ivl_expr_t retrieved by the
|
||||
* ivl_stmt_rval function. In this case, the run time is expected to
|
||||
* calculate the value of the expression at the assignment, then
|
||||
* continuous assign that constant value.
|
||||
*
|
||||
* If the ivl_stmt_rval for a CASSIGN is nil, then the ivl_stmt_nexus
|
||||
* function instead contains a nexus that should be connected at run
|
||||
* time to the l-value.
|
||||
*/
|
||||
|
||||
/* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
|
|
@ -1236,6 +1315,11 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.127 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.126 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
11
main.cc
11
main.cc
|
|
@ -19,7 +19,7 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.86 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.87 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -137,7 +137,9 @@ extern void synth(Design*des);
|
|||
extern void synth2(Design*des);
|
||||
extern void syn_rules(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
#ifdef WITH_T_XNF
|
||||
extern void xnfio(Design*des);
|
||||
#endif
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
|
|
@ -149,7 +151,9 @@ static struct net_func_map {
|
|||
{ "synth", &synth },
|
||||
{ "synth2", &synth2 },
|
||||
{ "syn-rules", &syn_rules },
|
||||
#ifdef WITH_T_XNF
|
||||
{ "xnfio", &xnfio },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
@ -744,6 +748,11 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.87 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.86 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_assign.cc,v 1.18 2004/08/28 15:08:31 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.19 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -42,7 +42,7 @@ NetAssign_::NetAssign_(NetNet*s)
|
|||
: sig_(s), mem_(0), var_(0), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = sig_->pin_count();
|
||||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ void NetAssign_::set_part(unsigned lo, unsigned lw)
|
|||
loff_ = lo;
|
||||
lwid_ = lw;
|
||||
if (sig_) {
|
||||
assert(sig_->pin_count() >= (lo + lw));
|
||||
assert(sig_->vector_width() >= (lo + lw));
|
||||
} else {
|
||||
assert(mem_);
|
||||
assert(lwid_ == mem_->width());
|
||||
|
|
@ -259,8 +259,49 @@ NetAssignNB::~NetAssignNB()
|
|||
{
|
||||
}
|
||||
|
||||
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetAssign_*l)
|
||||
: NetAssignBase(l, 0)
|
||||
{
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
}
|
||||
|
||||
NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetAssign_*l)
|
||||
: NetAssignBase(l, 0)
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.19 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/08/28 15:08:31 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
*
|
||||
|
|
@ -270,37 +311,5 @@ NetAssignNB::~NetAssignNB()
|
|||
* Revision 1.16 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.15 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.14 2002/08/04 18:28:15 steve
|
||||
* Do not use hierarchical names of memories to
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
*
|
||||
* Revision 1.13 2002/07/02 03:02:57 steve
|
||||
* Change the signal to a net when assignments go away.
|
||||
*
|
||||
* Revision 1.12 2002/06/08 23:42:46 steve
|
||||
* Add NetRamDq synthsesis from memory l-values.
|
||||
*
|
||||
* Revision 1.11 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.10 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.9 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*/
|
||||
|
||||
|
|
|
|||
108
net_force.cc
108
net_force.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_force.cc,v 1.12 2004/02/18 17:11:56 steve Exp $"
|
||||
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -33,110 +33,14 @@
|
|||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* Construct the procedural continuous assignment statement. This is a
|
||||
* bit different from a normal assignment because the the lval is only
|
||||
* intermittently connected. The deassign in particular disconnects
|
||||
* the signals when they are not being assigned anymore. Because of
|
||||
* this, there is no other reference to the lval to make it stay put
|
||||
* so we increment the eref.
|
||||
*
|
||||
* XXXX I'm not sure this is the right way. Perhaps I should create
|
||||
* output pins to connect to the netlist? But that would cause the
|
||||
* link ring to grow, and that is not quite correct either. Hmm...
|
||||
*/
|
||||
NetCAssign::NetCAssign(NetScope*s, perm_string n, NetNet*l)
|
||||
: NetNode(s, n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet* NetCAssign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
const Link& NetCAssign::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet*NetDeassign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetForce::NetForce(NetScope*s, perm_string n, NetNet*l)
|
||||
: NetNode(s, n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const Link& NetForce::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
const NetNet* NetForce::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
/* Put myself into a release list that the net is
|
||||
keeping. This is so that the NetNet can detach itself if
|
||||
and when it is deleted by the optimizer. */
|
||||
release_next_ = lval_->release_list_;
|
||||
lval_->release_list_ = this;
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
assert(lval_ == 0);
|
||||
}
|
||||
|
||||
const NetNet*NetRelease::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_force.cc,v $
|
||||
* Revision 1.13 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.12 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
220
netlist.cc
220
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.cc,v 1.226 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.227 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -227,14 +227,12 @@ NetNode::~NetNode()
|
|||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, npins), sig_next_(0), sig_prev_(0),
|
||||
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
|
||||
type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
release_list_ = 0;
|
||||
|
||||
verinum::V init_value = verinum::Vz;
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
|
|
@ -257,25 +255,21 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
|||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
pin(idx).set_dir(dir);
|
||||
pin(idx).set_init(init_value);
|
||||
}
|
||||
pin(0).set_name(perm_string::literal("P"), 0);
|
||||
pin(0).set_dir(dir);
|
||||
pin(0).set_init(init_value);
|
||||
|
||||
scope()->add_signal(this);
|
||||
s->add_signal(this);
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
||||
: NetObj(s, n, ((ms>ls)?ms-ls:ls-ms) + 1),
|
||||
: NetObj(s, n, 1),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
release_list_ = 0;
|
||||
|
||||
verinum::V init_value = verinum::Vz;
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
|
|
@ -297,11 +291,9 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
|||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
pin(idx).set_dir(dir);
|
||||
pin(idx).set_init(init_value);
|
||||
}
|
||||
pin(0).set_name(perm_string::literal("P"), 0);
|
||||
pin(0).set_dir(dir);
|
||||
pin(0).set_init(init_value);
|
||||
|
||||
s->add_signal(this);
|
||||
}
|
||||
|
|
@ -325,14 +317,6 @@ NetNet::~NetNet()
|
|||
if (scope())
|
||||
scope()->rem_signal(this);
|
||||
|
||||
/* Detach me from all the NetRelease objects that refer to me. */
|
||||
while (release_list_) {
|
||||
NetRelease*tmp = release_list_;
|
||||
release_list_ = tmp->release_next_;
|
||||
assert(tmp->lval_ == this);
|
||||
tmp->lval_ = 0;
|
||||
tmp->release_next_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet::Type NetNet::type() const
|
||||
|
|
@ -409,6 +393,14 @@ long NetNet::msb() const
|
|||
return msb_;
|
||||
}
|
||||
|
||||
long NetNet::vector_width() const
|
||||
{
|
||||
if (msb_ > lsb_)
|
||||
return msb_ - lsb_ + 1;
|
||||
else
|
||||
return lsb_ - msb_ + 1;
|
||||
}
|
||||
|
||||
bool NetNet::sb_is_valid(long sb) const
|
||||
{
|
||||
if (msb_ >= lsb_)
|
||||
|
|
@ -464,7 +456,7 @@ unsigned NetNet::get_refs() const
|
|||
|
||||
|
||||
NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
|
||||
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid)
|
||||
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid-1,0)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(sig->pin(idx+off), pin(idx));
|
||||
|
|
@ -474,6 +466,33 @@ NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
|
|||
set_line(*sig);
|
||||
}
|
||||
|
||||
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid)
|
||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
||||
off_(off), wid_(wid)
|
||||
{
|
||||
connect(pin(1), sig->pin(0));
|
||||
set_line(*sig);
|
||||
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
pin(1).set_name(perm_string::literal("I"), 0);
|
||||
}
|
||||
|
||||
NetPartSelect::~NetPartSelect()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetPartSelect::width() const
|
||||
{
|
||||
return wid_;
|
||||
}
|
||||
|
||||
unsigned NetPartSelect::base() const
|
||||
{
|
||||
return off_;
|
||||
}
|
||||
|
||||
NetProc::NetProc()
|
||||
: next_(0)
|
||||
{
|
||||
|
|
@ -694,33 +713,31 @@ const verinum& NetFF::sset_value() const
|
|||
* 3 -- Cin
|
||||
* 4 -- Cout
|
||||
* 5 -- Overflow
|
||||
* 6 -- DataA[0]
|
||||
* 7 -- DataB[0]
|
||||
* 8 -- Result[0]
|
||||
* 6 -- DataA (normally a vector)
|
||||
* 7 -- DataB (normally a vector)
|
||||
* 8 -- Result (normally a vector)
|
||||
*/
|
||||
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, w*3+6)
|
||||
: NetNode(s, n, 9), width_(w)
|
||||
{
|
||||
pin(0).set_dir(Link::INPUT); pin(0).set_name(
|
||||
perm_string::literal("Add_Sub"), 0);
|
||||
pin(1).set_dir(Link::INPUT); pin(1).set_name(
|
||||
perm_string::literal("Aclr"), 0);
|
||||
pin(2).set_dir(Link::INPUT); pin(2).set_name(
|
||||
perm_string::literal("Clock"), 0);
|
||||
pin(3).set_dir(Link::INPUT); pin(3).set_name(
|
||||
perm_string::literal("Cin"), 0);
|
||||
pin(4).set_dir(Link::OUTPUT); pin(4).set_name(
|
||||
perm_string::literal("Cout"), 0);
|
||||
pin(5).set_dir(Link::OUTPUT); pin(5).set_name(
|
||||
perm_string::literal("Overflow"), 0);
|
||||
for (unsigned idx = 0 ; idx < w ; idx += 1) {
|
||||
pin_DataA(idx).set_dir(Link::INPUT);
|
||||
pin_DataB(idx).set_dir(Link::INPUT);
|
||||
pin_Result(idx).set_dir(Link::OUTPUT);
|
||||
pin_DataA(idx).set_name(perm_string::literal("DataA"), idx);
|
||||
pin_DataB(idx).set_name(perm_string::literal("DataB"), idx);
|
||||
pin_Result(idx).set_name(perm_string::literal("Result"), idx);
|
||||
}
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("Add_Sub"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Aclr"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("Clock"), 0);
|
||||
pin(3).set_dir(Link::INPUT);
|
||||
pin(3).set_name(perm_string::literal("Cin"), 0);
|
||||
pin(4).set_dir(Link::OUTPUT);
|
||||
pin(4).set_name(perm_string::literal("Cout"), 0);
|
||||
pin(5).set_dir(Link::OUTPUT);
|
||||
pin(5).set_name(perm_string::literal("Overflow"), 0);
|
||||
pin(6).set_dir(Link::INPUT);
|
||||
pin(6).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(7).set_dir(Link::INPUT);
|
||||
pin(7).set_name(perm_string::literal("DataB"), 0);
|
||||
pin(8).set_dir(Link::OUTPUT);
|
||||
pin(8).set_name(perm_string::literal("Result"), 0);
|
||||
}
|
||||
|
||||
NetAddSub::~NetAddSub()
|
||||
|
|
@ -729,7 +746,7 @@ NetAddSub::~NetAddSub()
|
|||
|
||||
unsigned NetAddSub::width()const
|
||||
{
|
||||
return (pin_count() - 6) / 3;
|
||||
return width_;
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_Cout()
|
||||
|
|
@ -742,46 +759,34 @@ const Link& NetAddSub::pin_Cout() const
|
|||
return pin(4);
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_DataA(unsigned idx)
|
||||
Link& NetAddSub::pin_DataA()
|
||||
{
|
||||
idx = 6 + idx*3;
|
||||
assert(idx < pin_count());
|
||||
return pin(idx);
|
||||
return pin(6);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_DataA(unsigned idx) const
|
||||
const Link& NetAddSub::pin_DataA() const
|
||||
{
|
||||
idx = 6 + idx*3;
|
||||
assert(idx < pin_count());
|
||||
return pin(idx);
|
||||
return pin(6);
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_DataB(unsigned idx)
|
||||
Link& NetAddSub::pin_DataB()
|
||||
{
|
||||
idx = 7 + idx*3;
|
||||
assert(idx < pin_count());
|
||||
return pin(idx);
|
||||
return pin(7);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_DataB(unsigned idx) const
|
||||
const Link& NetAddSub::pin_DataB() const
|
||||
{
|
||||
idx = 7 + idx*3;
|
||||
assert(idx < pin_count());
|
||||
return pin(idx);
|
||||
return pin(7);
|
||||
}
|
||||
|
||||
Link& NetAddSub::pin_Result(unsigned idx)
|
||||
Link& NetAddSub::pin_Result()
|
||||
{
|
||||
idx = 8 + idx*3;
|
||||
assert(idx < pin_count());
|
||||
return pin(idx);
|
||||
return pin(8);
|
||||
}
|
||||
|
||||
const Link& NetAddSub::pin_Result(unsigned idx) const
|
||||
const Link& NetAddSub::pin_Result() const
|
||||
{
|
||||
idx = 8 + idx*3;
|
||||
assert(idx < pin_count());
|
||||
return pin(idx);
|
||||
return pin(8);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1591,8 +1596,8 @@ const Link& NetRamDq::pin_Q(unsigned idx) const
|
|||
return pin(3+awidth_+width()+idx);
|
||||
}
|
||||
|
||||
NetBUFZ::NetBUFZ(NetScope*s, perm_string n)
|
||||
: NetNode(s, n, 2)
|
||||
NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, 2), width_(w)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
|
|
@ -1604,6 +1609,10 @@ NetBUFZ::~NetBUFZ()
|
|||
{
|
||||
}
|
||||
|
||||
unsigned NetBUFZ::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n)
|
||||
: NetNode(s, n, 3)
|
||||
|
|
@ -1656,7 +1665,7 @@ NetProc* NetCondit::else_clause()
|
|||
}
|
||||
|
||||
NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
|
||||
: NetNode(s, n, 1)
|
||||
: NetNode(s, n, 1), width_(1)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
|
|
@ -1665,12 +1674,12 @@ NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
|
|||
}
|
||||
|
||||
NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
|
||||
: NetNode(s, n, val.len())
|
||||
: NetNode(s, n, 1), width_(val.len())
|
||||
{
|
||||
value_ = new verinum::V[pin_count()];
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::OUTPUT);
|
||||
pin(idx).set_name(perm_string::literal("O"), idx);
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
value_ = new verinum::V[width_];
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
value_[idx] = val.get(idx);
|
||||
}
|
||||
}
|
||||
|
|
@ -1682,10 +1691,15 @@ NetConst::~NetConst()
|
|||
|
||||
verinum::V NetConst::value(unsigned idx) const
|
||||
{
|
||||
assert(idx < pin_count());
|
||||
assert(idx < width_);
|
||||
return value_[idx];
|
||||
}
|
||||
|
||||
unsigned NetConst::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
|
||||
: scope_(s), statement_(0), result_sig_(result), result_var_(0), ports_(po)
|
||||
{
|
||||
|
|
@ -2071,15 +2085,14 @@ const NetScope* NetEScope::scope() const
|
|||
}
|
||||
|
||||
NetESignal::NetESignal(NetNet*n)
|
||||
: NetExpr(n->pin_count()), net_(n)
|
||||
: NetExpr(n->vector_width()), net_(n)
|
||||
{
|
||||
msi_ = n->pin_count() - 1;
|
||||
lsi_ = 0;
|
||||
net_->incr_eref();
|
||||
set_line(*n);
|
||||
cast_signed(net_->get_signed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
|
||||
: NetExpr(m - l + 1), net_(n)
|
||||
{
|
||||
|
|
@ -2090,6 +2103,7 @@ NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
|
|||
set_line(*n);
|
||||
cast_signed(net_->get_signed());
|
||||
}
|
||||
#endif
|
||||
|
||||
NetESignal::~NetESignal()
|
||||
{
|
||||
|
|
@ -2103,13 +2117,13 @@ perm_string NetESignal::name() const
|
|||
|
||||
unsigned NetESignal::bit_count() const
|
||||
{
|
||||
return msi_ - lsi_ + 1;
|
||||
return net_->vector_width();
|
||||
}
|
||||
|
||||
Link& NetESignal::bit(unsigned idx)
|
||||
{
|
||||
assert(idx <= (msi_ - lsi_));
|
||||
return net_->pin(idx + lsi_);
|
||||
assert(idx <= 0);
|
||||
return net_->pin(idx);
|
||||
}
|
||||
|
||||
const NetNet* NetESignal::sig() const
|
||||
|
|
@ -2119,12 +2133,12 @@ const NetNet* NetESignal::sig() const
|
|||
|
||||
unsigned NetESignal::lsi() const
|
||||
{
|
||||
return lsi_;
|
||||
return net_->lsb();
|
||||
}
|
||||
|
||||
unsigned NetESignal::msi() const
|
||||
{
|
||||
return msi_;
|
||||
return net_->msb();
|
||||
}
|
||||
|
||||
NetEBitSel::NetEBitSel(NetESignal*sig, NetExpr*ex)
|
||||
|
|
@ -2231,8 +2245,9 @@ NetEUReduce::~NetEUReduce()
|
|||
{
|
||||
}
|
||||
|
||||
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t)
|
||||
: NetNode(s, n, pins), type_(t)
|
||||
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
|
||||
TYPE t, unsigned wid)
|
||||
: NetNode(s, n, pins), type_(t), width_(wid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
|
|
@ -2242,6 +2257,16 @@ NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t)
|
|||
}
|
||||
}
|
||||
|
||||
NetLogic::TYPE NetLogic::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
unsigned NetLogic::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
|
||||
: name_(n), proc_(0), ports_(po)
|
||||
{
|
||||
|
|
@ -2281,6 +2306,11 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.227 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.226 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
143
netlist.h
143
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.321 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.322 2004/12/11 02:31:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -345,8 +345,11 @@ class NetNode : public NetObj {
|
|||
/*
|
||||
* NetNet is a special kind of NetObj that doesn't really do anything,
|
||||
* but carries the properties of the wire/reg/trireg, including its
|
||||
* name. A scalar wire is a NetNet with one pin, a vector a wider
|
||||
* NetNet. NetNet objects also appear as side effects of synthesis or
|
||||
* name. Scalers and vectors are all the same thing here, a NetNet
|
||||
* with a single pin. The difference between a scaler and vector is
|
||||
* the video of the atomic vector datum it carries.
|
||||
*
|
||||
* NetNet objects can also appear as side effects of synthesis or
|
||||
* other abstractions.
|
||||
*
|
||||
* Note that INTEGER types are an alias for a ``reg signed [31:0]''.
|
||||
|
|
@ -357,7 +360,7 @@ class NetNode : public NetObj {
|
|||
*
|
||||
* NetNet objects are located by searching NetScope objects.
|
||||
*
|
||||
* All the pins of a NetNet object are PASSIVE: they do not drive
|
||||
* The pin of a NetNet object are PASSIVE: they do not drive
|
||||
* anything and they are not a data sink, per se. The pins follow the
|
||||
* values on the nexus.
|
||||
*/
|
||||
|
|
@ -397,6 +400,7 @@ class NetNet : public NetObj {
|
|||
reg [1:8] has 8 bits, msb==1 and lsb==8. */
|
||||
long msb() const;
|
||||
long lsb() const;
|
||||
long vector_width() const;
|
||||
|
||||
/* This method converts a signed index (the type that might be
|
||||
found in the verilog source) to a pin number. It accounts
|
||||
|
|
@ -431,12 +435,6 @@ class NetNet : public NetObj {
|
|||
friend class NetScope;
|
||||
NetNet*sig_next_, *sig_prev_;
|
||||
|
||||
// Keep a list of release statements that reference me. I may
|
||||
// need to know this in order to fix them up when I am
|
||||
// deleted.
|
||||
friend class NetRelease;
|
||||
NetRelease*release_list_;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
PortType port_type_;
|
||||
|
|
@ -472,18 +470,21 @@ class NetAddSub : public NetNode {
|
|||
Link& pin_Cout();
|
||||
Link& pin_Overflow();
|
||||
|
||||
Link& pin_DataA(unsigned idx);
|
||||
Link& pin_DataB(unsigned idx);
|
||||
Link& pin_Result(unsigned idx);
|
||||
Link& pin_DataA();
|
||||
Link& pin_DataB();
|
||||
Link& pin_Result();
|
||||
|
||||
const Link& pin_Cout() const;
|
||||
const Link& pin_DataA(unsigned idx) const;
|
||||
const Link& pin_DataB(unsigned idx) const;
|
||||
const Link& pin_Result(unsigned idx) const;
|
||||
const Link& pin_DataA() const;
|
||||
const Link& pin_DataB() const;
|
||||
const Link& pin_Result() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1122,7 +1123,7 @@ class NetECRealParam : public NetECReal {
|
|||
perm_string name_;
|
||||
};
|
||||
|
||||
/*
|
||||
/* DEPRECATED -- REMOVE ME! Use NetPartSelect instead.
|
||||
* This is a special, magical NetNet object. It represents a constant
|
||||
* bit or part select of another NetNet, so is used to return that
|
||||
* selection from elaborate function. None of these should remain once
|
||||
|
|
@ -1135,6 +1136,29 @@ class NetSubnet : public NetNet {
|
|||
virtual void dump_net(ostream&, unsigned) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetPartSelect device represents an r-value part select of a
|
||||
* signal. The output (pin 0) is a vector that is a part select of the
|
||||
* input (pin 1). The part to be selected is the canonical (0-based)
|
||||
* offset and the specified number of bits (wid).
|
||||
*/
|
||||
class NetPartSelect : public NetNode {
|
||||
|
||||
public:
|
||||
explicit NetPartSelect(NetNet*sig, unsigned off, unsigned wid);
|
||||
~NetPartSelect();
|
||||
|
||||
unsigned width() const;
|
||||
unsigned base() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
bool emit_node(struct target_t*tgt) const;
|
||||
|
||||
private:
|
||||
unsigned off_;
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetBUFZ is a magic device that represents the continuous
|
||||
* assign, with the output being the target register and the input
|
||||
|
|
@ -1145,11 +1169,16 @@ class NetSubnet : public NetNet {
|
|||
class NetBUFZ : public NetNode {
|
||||
|
||||
public:
|
||||
explicit NetBUFZ(NetScope*s, perm_string n);
|
||||
explicit NetBUFZ(NetScope*s, perm_string n, unsigned wid);
|
||||
~NetBUFZ();
|
||||
|
||||
unsigned width() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1189,12 +1218,14 @@ class NetConst : public NetNode {
|
|||
~NetConst();
|
||||
|
||||
verinum::V value(unsigned idx) const;
|
||||
unsigned width() const;
|
||||
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
virtual void functor_node(Design*, functor_t*);
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
verinum::V*value_;
|
||||
};
|
||||
|
||||
|
|
@ -1219,16 +1250,19 @@ class NetLogic : public NetNode {
|
|||
NOTIF0, NOTIF1, OR, PULLDOWN, PULLUP, RNMOS, RPMOS,
|
||||
PMOS, XNOR, XOR };
|
||||
|
||||
explicit NetLogic(NetScope*s, perm_string n, unsigned pins, TYPE t);
|
||||
explicit NetLogic(NetScope*s, perm_string n, unsigned pins,
|
||||
TYPE t, unsigned wid);
|
||||
|
||||
TYPE type() const { return type_; }
|
||||
TYPE type() const;
|
||||
unsigned width() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
virtual void functor_node(Design*, functor_t*);
|
||||
|
||||
private:
|
||||
const TYPE type_;
|
||||
TYPE type_;
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1627,31 +1661,17 @@ class NetCase : public NetProc {
|
|||
/*
|
||||
* The cassign statement causes the r-val net to be forced onto the
|
||||
* l-val reg when it is executed. The code generator is expected to
|
||||
* know what that means. All the expressions are structural and behave
|
||||
* like nets.
|
||||
*
|
||||
* This class is a NetProc because it it turned on by procedural
|
||||
* behavior. However, it is also a NetNode because it connects to
|
||||
* nets, and when activated follows the net values.
|
||||
* know what that means.
|
||||
*/
|
||||
class NetCAssign : public NetProc, public NetNode {
|
||||
class NetCAssign : public NetAssignBase {
|
||||
|
||||
public:
|
||||
explicit NetCAssign(NetScope*s, perm_string n, NetNet*l);
|
||||
explicit NetCAssign(NetAssign_*lv, NetExpr*rv);
|
||||
~NetCAssign();
|
||||
|
||||
const Link& lval_pin(unsigned) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
const NetNet*lval() const;
|
||||
|
||||
private:
|
||||
NetNet*lval_;
|
||||
|
||||
private: // not implemented
|
||||
NetCAssign(const NetCAssign&);
|
||||
|
|
@ -1709,20 +1729,15 @@ class NetCondit : public NetProc {
|
|||
* lval is the expression of the "deassign <expr>;" statement with the
|
||||
* expr elaborated to a net.
|
||||
*/
|
||||
class NetDeassign : public NetProc {
|
||||
class NetDeassign : public NetAssignBase {
|
||||
|
||||
public:
|
||||
explicit NetDeassign(NetNet*l);
|
||||
explicit NetDeassign(NetAssign_*l);
|
||||
~NetDeassign();
|
||||
|
||||
const NetNet*lval() const;
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetNet*lval_;
|
||||
|
||||
private: // not implemented
|
||||
NetDeassign(const NetDeassign&);
|
||||
NetDeassign& operator= (const NetDeassign&);
|
||||
|
|
@ -1957,32 +1972,18 @@ class NetEvProbe : public NetNode {
|
|||
/*
|
||||
* The force statement causes the r-val net to be forced onto the
|
||||
* l-val net when it is executed. The code generator is expected to
|
||||
* know what that means. All the expressions are structural and behave
|
||||
* like nets.
|
||||
*
|
||||
* This class is a NetProc because it it turned on by procedural
|
||||
* behavior. However, it is also a NetNode because it connects to
|
||||
* nets, and when activated follows the net values.
|
||||
* know what that means.
|
||||
*/
|
||||
class NetForce : public NetProc, public NetNode {
|
||||
class NetForce : public NetAssignBase {
|
||||
|
||||
public:
|
||||
explicit NetForce(NetScope*s, perm_string n, NetNet*l);
|
||||
explicit NetForce(NetAssign_*l, NetExpr*r);
|
||||
~NetForce();
|
||||
|
||||
const Link& lval_pin(unsigned) const;
|
||||
|
||||
const NetNet*lval() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
NetNet*lval_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -2110,22 +2111,16 @@ class NetRepeat : public NetProc {
|
|||
* lval is the expression of the "release <expr>;" statement with the
|
||||
* expr elaborated to a net.
|
||||
*/
|
||||
class NetRelease : public NetProc {
|
||||
class NetRelease : public NetAssignBase {
|
||||
|
||||
public:
|
||||
explicit NetRelease(NetNet*l);
|
||||
explicit NetRelease(NetAssign_*l);
|
||||
~NetRelease();
|
||||
|
||||
const NetNet*lval() const;
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetNet*lval_;
|
||||
// Used to manage list within NetNet objects.
|
||||
friend class NetNet;
|
||||
NetRelease*release_next_;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -2954,7 +2949,6 @@ class NetESignal : public NetExpr {
|
|||
|
||||
public:
|
||||
NetESignal(NetNet*n);
|
||||
NetESignal(NetNet*n, unsigned msi, unsigned lsi);
|
||||
~NetESignal();
|
||||
|
||||
perm_string name() const;
|
||||
|
|
@ -2978,8 +2972,6 @@ class NetESignal : public NetExpr {
|
|||
|
||||
private:
|
||||
NetNet*net_;
|
||||
unsigned msi_;
|
||||
unsigned lsi_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3357,6 +3349,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.322 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.321 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
13
netmisc.cc
13
netmisc.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $"
|
||||
#ident "$Id: netmisc.cc,v 1.9 2004/12/11 02:31:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -30,7 +30,7 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
|||
{
|
||||
if (val == 0)
|
||||
return sig;
|
||||
|
||||
#if 0
|
||||
NetScope*scope = sig->scope();
|
||||
unsigned long abs_val = (val >= 0)? val : (-val);
|
||||
unsigned width = sig->pin_count();
|
||||
|
|
@ -70,6 +70,10 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
|||
des->add_node(val_c);
|
||||
|
||||
return res;
|
||||
#else
|
||||
cerr << sig->get_line() << ": XXXX: Forgot how to implement add_to_net" << endl;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -90,6 +94,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
|||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.9 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.8 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
9
pform.cc
9
pform.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.cc,v 1.129 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.130 2004/12/11 02:31:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -952,7 +952,7 @@ void pform_make_modgates(perm_string type,
|
|||
delete gates;
|
||||
}
|
||||
|
||||
PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
svector<PExpr*>*del,
|
||||
struct str_pair_t str)
|
||||
{
|
||||
|
|
@ -1597,6 +1597,11 @@ int pform_parse(const char*path, FILE*file)
|
|||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.130 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.129 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
10
pform.h
10
pform.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.82 2004/12/11 02:31:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -270,9 +270,6 @@ extern void pform_make_modgates(perm_string type,
|
|||
svector<lgate>*gates);
|
||||
|
||||
/* Make a continuous assignment node, with optional bit- or part- select. */
|
||||
extern PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
svector<PExpr*>*delays,
|
||||
struct str_pair_t str);
|
||||
extern void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
svector<PExpr*>*del,
|
||||
struct str_pair_t str,
|
||||
|
|
@ -298,6 +295,11 @@ extern void pform_dump(ostream&out, Module*mod);
|
|||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.82 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.81 2004/08/26 04:02:04 steve
|
||||
* Add support for localparam ranges.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: synth2.cc,v 1.39 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.40 2004/12/11 02:31:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -768,7 +768,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
|||
if (ff->pin_Enable().is_linked()) {
|
||||
NetLogic*ce_and = new NetLogic(scope,
|
||||
scope->local_symbol(), 3,
|
||||
NetLogic::AND);
|
||||
NetLogic::AND, 1);
|
||||
des->add_node(ce_and);
|
||||
connect(ff->pin_Enable(), ce_and->pin(1));
|
||||
connect(ce->pin(0), ce_and->pin(2));
|
||||
|
|
@ -985,6 +985,11 @@ void synth2(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.40 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.39 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
157
t-dll-api.cc
157
t-dll-api.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.108 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.109 2004/12/11 02:31:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -129,20 +129,10 @@ extern "C" const char*ivl_const_bits(ivl_net_const_t net)
|
|||
return net->b.bits_;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx)
|
||||
extern "C" ivl_nexus_t ivl_const_nex(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->width_);
|
||||
if (net->width_ == 1)
|
||||
return net->n.pin_;
|
||||
else
|
||||
return net->n.pins_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_const_pins(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
return net->pin_;
|
||||
}
|
||||
|
||||
extern "C" int ivl_const_signed(ivl_net_const_t net)
|
||||
|
|
@ -151,6 +141,12 @@ extern "C" int ivl_const_signed(ivl_net_const_t net)
|
|||
return net->signed_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_const_width(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_event_name(ivl_event_t net)
|
||||
{
|
||||
static char*name_buffer = 0;
|
||||
|
|
@ -585,6 +581,11 @@ extern "C" unsigned ivl_logic_delay(ivl_net_logic_t net, unsigned transition)
|
|||
return net->delay[transition];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_logic_width(ivl_net_logic_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_udp_sequ(ivl_udp_t net)
|
||||
{
|
||||
|
|
@ -673,6 +674,18 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_PART:
|
||||
return net->u_.part.base;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
@ -749,8 +762,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.a[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.a;
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
|
|
@ -765,6 +778,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.d.pins[idx];
|
||||
|
||||
case IVL_LPM_PART:
|
||||
assert(idx == 0);
|
||||
return net->u_.part.a;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -785,8 +802,8 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
|||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.b[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.b;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -873,15 +890,15 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.q[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_NE:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q[0];
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
|
|
@ -907,6 +924,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.ufunc.port_wid[0]);
|
||||
return net->u_.ufunc.pins[idx];
|
||||
|
||||
case IVL_LPM_PART:
|
||||
assert(idx == 0);
|
||||
return net->u_.part.q;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -987,6 +1008,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
return 0;
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_PART:
|
||||
return net->u_.part.signed_flag;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1035,6 +1058,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
|||
return net->u_.shift.width;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.port_wid[0];
|
||||
case IVL_LPM_PART:
|
||||
return net->u_.part.width;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1091,12 +1116,20 @@ extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
|
|||
return net->loff_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
|
||||
extern "C" unsigned ivl_lval_width(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
#if 0
|
||||
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
|
|
@ -1104,6 +1137,7 @@ extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
|
|||
assert(net->type_ != IVL_LVAL_MEM);
|
||||
return ivl_signal_pin(net->n.sig, idx+net->loff_);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
|
||||
{
|
||||
|
|
@ -1504,21 +1538,9 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
|
|||
return name_buffer;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx)
|
||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->width_);
|
||||
if (net->width_ == 1) {
|
||||
return net->n.pin_;
|
||||
|
||||
} else {
|
||||
return net->n.pins_[idx];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_pins(ivl_signal_t net)
|
||||
{
|
||||
return net->width_;
|
||||
return net->pin_;
|
||||
}
|
||||
|
||||
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
||||
|
|
@ -1532,6 +1554,11 @@ extern "C" int ivl_signal_lsb(ivl_signal_t net)
|
|||
return net->lsb_index;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_width(ivl_signal_t net)
|
||||
{
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
|
||||
{
|
||||
return net->port_;
|
||||
|
|
@ -1760,15 +1787,12 @@ extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx)
|
|||
switch (net->type_) {
|
||||
case IVL_ST_ASSIGN:
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
assert(idx < net->u_.assign_.lvals_);
|
||||
return net->u_.assign_.lval_ + idx;
|
||||
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_DEASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
case IVL_ST_RELEASE:
|
||||
assert(idx < net->u_.cassign_.lvals);
|
||||
return net->u_.cassign_.lval + idx;
|
||||
assert(idx < net->u_.assign_.lvals_);
|
||||
return net->u_.assign_.lval_ + idx;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -1781,13 +1805,11 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
|
|||
switch (net->type_) {
|
||||
case IVL_ST_ASSIGN:
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
return net->u_.assign_.lvals_;
|
||||
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_DEASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
case IVL_ST_RELEASE:
|
||||
return net->u_.cassign_.lvals;
|
||||
return net->u_.assign_.lvals_;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -1798,17 +1820,25 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
|
|||
extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
||||
{
|
||||
assert((net->type_ == IVL_ST_ASSIGN)
|
||||
|| (net->type_ == IVL_ST_ASSIGN_NB));
|
||||
|| (net->type_ == IVL_ST_ASSIGN_NB)
|
||||
|| (net->type_ == IVL_ST_CASSIGN)
|
||||
|| (net->type_ == IVL_ST_DEASSIGN));
|
||||
|
||||
unsigned sum = 0;
|
||||
for (unsigned idx = 0 ; idx < net->u_.assign_.lvals_ ; idx += 1) {
|
||||
ivl_lval_t cur = net->u_.assign_.lval_ + idx;
|
||||
|
||||
unsigned nlvals;
|
||||
struct ivl_lval_s*lvals;
|
||||
nlvals = net->u_.assign_.lvals_;
|
||||
lvals = net->u_.assign_.lval_;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nlvals ; idx += 1) {
|
||||
ivl_lval_t cur = lvals + idx;
|
||||
switch(cur->type_) {
|
||||
case IVL_LVAL_MUX:
|
||||
sum += 1;
|
||||
break;
|
||||
case IVL_LVAL_REG:
|
||||
sum += ivl_lval_pins(cur);
|
||||
sum += ivl_lval_width(cur);
|
||||
break;
|
||||
case IVL_LVAL_MEM:
|
||||
sum += ivl_memory_width(ivl_lval_mem(cur));
|
||||
|
|
@ -1836,33 +1866,6 @@ extern "C" const char* ivl_stmt_name(ivl_statement_t net)
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
assert(idx < net->u_.cassign_.npins);
|
||||
return net->u_.cassign_.pins[idx];
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_stmt_nexus_count(ivl_statement_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
return net->u_.cassign_.npins;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
|
|
@ -1892,6 +1895,7 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net)
|
|||
switch (net->type_) {
|
||||
case IVL_ST_ASSIGN:
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
case IVL_ST_CASSIGN:
|
||||
return net->u_.assign_.rval_;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -1935,6 +1939,11 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.109 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.108 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
260
t-dll-proc.cc
260
t-dll-proc.cc
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-proc.cc,v 1.65 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.66 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -145,90 +145,15 @@ bool dll_target::func_def(const NetScope*net)
|
|||
}
|
||||
|
||||
/*
|
||||
* This private function makes the assignment lvals for the various
|
||||
* kinds of assignment statements.
|
||||
*/
|
||||
void dll_target::proc_assign(const NetAssign*net)
|
||||
void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
||||
{
|
||||
unsigned cnt;
|
||||
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN;
|
||||
|
||||
stmt_cur_->u_.assign_.lvals_ = cnt = net->l_val_count();
|
||||
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
||||
/* The assignment may have multiple concatenated
|
||||
l-values. Scan them and accumulate an ivl_lval_t list. */
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
|
||||
const NetAssign_*asn = net->l_val(idx);
|
||||
|
||||
cur->width_ = asn->lwidth();
|
||||
cur->loff_ = asn->get_loff();
|
||||
if (asn->sig()) {
|
||||
cur->type_ = IVL_LVAL_REG;
|
||||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
|
||||
cur->idx = 0;
|
||||
if (asn->bmux()) {
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
|
||||
if (cur->n.sig->lsb_index != 0)
|
||||
sub_off_from_expr_(asn->sig()->lsb());
|
||||
if (cur->n.sig->lsb_dist != 1)
|
||||
mul_expr_by_const_(cur->n.sig->lsb_dist);
|
||||
|
||||
cur->type_ = IVL_LVAL_MUX;
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
} else if (asn->var()) {
|
||||
cur->type_ = IVL_LVAL_VAR;
|
||||
cur->idx = 0;
|
||||
cur->n.var = find_variable(des_, asn->var());
|
||||
|
||||
} else {
|
||||
assert(asn->mem());
|
||||
cur->type_ = IVL_LVAL_MEM;
|
||||
cur->n.mem = find_memory(des_, asn->mem());
|
||||
assert(cur->n.mem);
|
||||
cur->width_ = ivl_memory_width(cur->n.mem);
|
||||
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
const NetExpr*del = net->get_delay();
|
||||
if (del) {
|
||||
del->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.delay = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dll_target::proc_assign_nb(const NetAssignNB*net)
|
||||
{
|
||||
unsigned cnt = net->l_val_count();
|
||||
|
||||
const NetExpr* delay_exp = net->get_delay();
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
|
||||
|
||||
stmt_cur_->u_.assign_.lvals_ = cnt;
|
||||
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
|
@ -276,7 +201,49 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
|
|||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void dll_target::proc_assign(const NetAssign*net)
|
||||
{
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN;
|
||||
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
||||
/* Make the lval fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
const NetExpr*del = net->get_delay();
|
||||
if (del) {
|
||||
del->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.delay = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dll_target::proc_assign_nb(const NetAssignNB*net)
|
||||
{
|
||||
const NetExpr* delay_exp = net->get_delay();
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
||||
/* Make the lval fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
/* Make the rval field. */
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
|
|
@ -428,27 +395,13 @@ bool dll_target::proc_cassign(const NetCAssign*net)
|
|||
|
||||
stmt_cur_->type_ = IVL_ST_CASSIGN;
|
||||
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
const NetNet*lsig = net->lval();
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
|
||||
|
||||
stmt_cur_->u_.cassign_.npins = net->pin_count();
|
||||
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
|
||||
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
|
||||
|
||||
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
|
||||
assert(ntmp[idx]);
|
||||
}
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -485,19 +438,9 @@ bool dll_target::proc_deassign(const NetDeassign*net)
|
|||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_DEASSIGN;
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
|
||||
const NetNet*lsig = net->lval();
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
|
||||
stmt_cur_->u_.cassign_.npins = 0;
|
||||
stmt_cur_->u_.cassign_.pins = 0;
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -554,52 +497,19 @@ bool dll_target::proc_disable(const NetDisable*net)
|
|||
|
||||
bool dll_target::proc_force(const NetForce*net)
|
||||
{
|
||||
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_FORCE;
|
||||
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
const NetNet*lsig = net->lval();
|
||||
assert(lsig);
|
||||
ivl_signal_t sig = find_signal(des_, lsig);
|
||||
assert(sig);
|
||||
|
||||
ivl_lval_type_t ltype;
|
||||
switch (sig->type_) {
|
||||
case IVL_SIT_REG:
|
||||
ltype = IVL_LVAL_REG;
|
||||
break;
|
||||
case IVL_SIT_TRI:
|
||||
case IVL_SIT_TRI0:
|
||||
case IVL_SIT_TRI1:
|
||||
ltype = IVL_LVAL_NET;
|
||||
break;
|
||||
default:
|
||||
cerr << net->get_line() << ": internal error: Sorry, "
|
||||
<< "force to nets not supported by this target."
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
|
||||
|
||||
stmt_cur_->u_.cassign_.npins = net->pin_count();
|
||||
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
|
||||
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
|
||||
|
||||
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
|
||||
assert(ntmp[idx]);
|
||||
}
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -630,47 +540,8 @@ bool dll_target::proc_release(const NetRelease*net)
|
|||
|
||||
stmt_cur_->type_ = IVL_ST_RELEASE;
|
||||
|
||||
/* If there is no signal attached to the release, then it is
|
||||
the victim of an elided net. In that case, simply state
|
||||
that there are no lvals, and that's all. */
|
||||
const NetNet*lsig = net->lval();
|
||||
if (lsig == 0) {
|
||||
stmt_cur_->u_.cassign_.lvals = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(lsig);
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
|
||||
|
||||
ivl_signal_t sig = find_signal(des_, lsig);
|
||||
assert(sig);
|
||||
|
||||
ivl_lval_type_t ltype;
|
||||
switch (sig->type_) {
|
||||
case IVL_SIT_REG:
|
||||
ltype = IVL_LVAL_REG;
|
||||
break;
|
||||
case IVL_SIT_TRI:
|
||||
case IVL_SIT_TRI0:
|
||||
case IVL_SIT_TRI1:
|
||||
ltype = IVL_LVAL_NET;
|
||||
break;
|
||||
default:
|
||||
cerr << net->get_line() << ": internal error: Sorry, "
|
||||
<< "force/release to nets not supported by this target."
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -872,6 +743,11 @@ void dll_target::proc_while(const NetWhile*net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.66 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.65 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
194
t-dll.cc
194
t-dll.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.131 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.132 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -650,8 +650,8 @@ bool dll_target::bufz(const NetBUFZ*net)
|
|||
assert(net->pin_count() == 2);
|
||||
|
||||
obj->type_ = IVL_LO_BUFZ;
|
||||
|
||||
obj->npins_ = 2;
|
||||
obj->width_= net->width();
|
||||
obj->npins_= 2;
|
||||
obj->pins_ = new ivl_nexus_t[2];
|
||||
|
||||
/* Get the ivl_nexus_t objects connected to the two pins.
|
||||
|
|
@ -780,6 +780,8 @@ void dll_target::logic(const NetLogic*net)
|
|||
{
|
||||
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
|
||||
|
||||
obj->width_ = net->width();
|
||||
|
||||
switch (net->type()) {
|
||||
case NetLogic::AND:
|
||||
obj->type_ = IVL_LO_AND;
|
||||
|
|
@ -943,16 +945,6 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
|||
scope_add_logic(scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::net_cassign(const NetCAssign*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dll_target::net_force(const NetForce*net)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* An IVL_LPM_UFUNC represents a node in a combinational expression
|
||||
* that calls a user defined function. I create an LPM object that has
|
||||
|
|
@ -1119,38 +1111,31 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
obj->u_.arith.width += 1;
|
||||
}
|
||||
|
||||
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
|
||||
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
|
||||
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
|
||||
const Nexus*nex;
|
||||
const Nexus*nex;
|
||||
|
||||
nex = net->pin_Result(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q[idx], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_DataA(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
nex = net->pin_DataA().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_DataB(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
nex = net->pin_DataB().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
/* If the carry output is connected, then connect the extra Q
|
||||
pin to the carry nexus and zero the a and b inputs. */
|
||||
if (net->pin_Cout().is_linked()) {
|
||||
#if 0
|
||||
unsigned carry = obj->u_.arith.width - 1;
|
||||
const Nexus*nex = net->pin_Cout().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
|
@ -1161,6 +1146,9 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
|
||||
obj->u_.arith.a[carry] = 0;
|
||||
obj->u_.arith.b[carry] = 0;
|
||||
#else
|
||||
cerr << "XXXX: t-dll.cc: Forgot how to connect cout." << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
|
@ -1252,7 +1240,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
|||
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
#if 0
|
||||
obj->u_.arith.q = new ivl_nexus_t[1 + 2 * obj->u_.arith.width];
|
||||
obj->u_.arith.a = obj->u_.arith.q + 1;
|
||||
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
|
||||
|
|
@ -1347,7 +1335,9 @@ void dll_target::lpm_compare(const NetCompare*net)
|
|||
nexus_lpm_add(obj->u_.arith.b[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
#else
|
||||
cerr << "XXXX: t-dll.cc: Forgot how to handle lpm_compare." << endl;
|
||||
#endif
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
|
@ -1365,7 +1355,7 @@ void dll_target::lpm_divide(const NetDivide*net)
|
|||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
#if 0
|
||||
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
|
||||
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
|
||||
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
|
||||
|
|
@ -1418,7 +1408,9 @@ void dll_target::lpm_divide(const NetDivide*net)
|
|||
obj->u_.arith.b[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
cerr << "XXXX t-dll.cc: Forgot how to handle lpm_divide." << endl;
|
||||
#endif
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
|
|
@ -1438,7 +1430,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
wid = net->width_b();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
|
||||
#if 0
|
||||
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
|
||||
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
|
||||
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
|
||||
|
|
@ -1485,7 +1477,9 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
obj->u_.arith.b[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
cerr << "XXXX: t-dll.cc: Forgot how to handle lpm_modulo." << endl;
|
||||
#endif
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
|
|
@ -1732,6 +1726,7 @@ void dll_target::lpm_mult(const NetMult*net)
|
|||
|
||||
obj->u_.arith.width = wid;
|
||||
|
||||
#if 0
|
||||
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
|
||||
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
|
||||
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
|
||||
|
|
@ -1791,7 +1786,9 @@ void dll_target::lpm_mult(const NetMult*net)
|
|||
obj->u_.arith.b[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
cerr << "XXXX: t-dll.cc: Forgot how to handle lpm_mult." << endl;
|
||||
#endif
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
|
|
@ -1870,6 +1867,42 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
|
||||
}
|
||||
|
||||
bool dll_target::part_select(const NetPartSelect*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_PART;
|
||||
obj->name = net->name(); // NetPartSelect names are permallocated.
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.part.signed_flag = 0;
|
||||
|
||||
/* Choose the width of the part select. */
|
||||
obj->u_.part.width = net->width();
|
||||
obj->u_.part.base = net->base();
|
||||
obj->u_.part.signed_flag = 0;
|
||||
const Nexus*nex;
|
||||
|
||||
/* NetPartSelect:pin(0) is the output pin. */
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.q = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.part.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
/* NetPartSelect:pin(1) is the input pin. */
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.a = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.part.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The assignment l-values are captured by the assignment statements
|
||||
* themselves in the process handling.
|
||||
|
|
@ -1885,7 +1918,10 @@ bool dll_target::net_const(const NetConst*net)
|
|||
|
||||
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
|
||||
|
||||
obj->width_ = net->pin_count();
|
||||
/* constants have a single vector output. */
|
||||
assert(net->pin_count() == 1);
|
||||
|
||||
obj->width_ = net->width();
|
||||
if (obj->width_ <= sizeof(char*)) {
|
||||
bits = obj->b.bit_;
|
||||
|
||||
|
|
@ -1913,30 +1949,14 @@ bool dll_target::net_const(const NetConst*net)
|
|||
/* Connect to all the nexus objects. Note that the one-bit
|
||||
case can be handled more efficiently without allocating
|
||||
array space. */
|
||||
if (obj->width_ == 1) {
|
||||
ivl_drive_t drv0, drv1;
|
||||
drive_from_link(net->pin(0), drv0, drv1);
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->n.pin_ = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_con_add(obj->n.pin_, obj, 0, drv0, drv1);
|
||||
|
||||
} else {
|
||||
obj->n.pins_ = new ivl_nexus_t[obj->width_];
|
||||
for (unsigned idx = 0 ; idx < obj->width_ ; idx += 1) {
|
||||
if (! net->pin(idx).is_linked())
|
||||
continue;
|
||||
ivl_drive_t drv0, drv1;
|
||||
drive_from_link(net->pin(0), drv0, drv1);
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pin_ = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_con_add(obj->pin_, obj, 0, drv0, drv1);
|
||||
|
||||
ivl_drive_t drv0, drv1;
|
||||
drive_from_link(net->pin(idx), drv0, drv1);
|
||||
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->n.pins_[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_con_add(obj->n.pins_[idx], obj, idx, drv0, drv1);
|
||||
}
|
||||
}
|
||||
|
||||
des_.nconsts += 1;
|
||||
des_.consts = (ivl_net_const_t*)
|
||||
|
|
@ -2057,7 +2077,7 @@ void dll_target::signal(const NetNet*net)
|
|||
/* Save the primitive properties of the signal in the
|
||||
ivl_signal_t object. */
|
||||
|
||||
obj->width_ = net->pin_count();
|
||||
obj->width_ = net->vector_width();
|
||||
obj->signed_= net->get_signed()? 1 : 0;
|
||||
obj->lsb_index = net->lsb();
|
||||
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1;
|
||||
|
|
@ -2140,39 +2160,18 @@ void dll_target::signal(const NetNet*net)
|
|||
t_cookie of the Nexus object so that I find it again when I
|
||||
next encounter the nexus. */
|
||||
|
||||
if (obj->width_ == 1) {
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
obj->n.pin_ = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->n.pin_, obj, 0);
|
||||
|
||||
} else {
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
|
||||
tmp->name_ = strings_.add(nex->name());
|
||||
nex->t_cookie(tmp);
|
||||
obj->n.pin_ = tmp;
|
||||
}
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
obj->pin_ = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->pin_, obj, 0);
|
||||
|
||||
} else {
|
||||
unsigned idx;
|
||||
|
||||
obj->n.pins_ = (ivl_nexus_t*)
|
||||
calloc(obj->width_, sizeof(ivl_nexus_t));
|
||||
|
||||
for (idx = 0 ; idx < obj->width_ ; idx += 1) {
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
obj->n.pins_[idx] = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->n.pins_[idx], obj, idx);
|
||||
|
||||
} else {
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, idx);
|
||||
tmp->name_ = strings_.add(nex->name());
|
||||
nex->t_cookie(tmp);
|
||||
obj->n.pins_[idx] = tmp;
|
||||
}
|
||||
}
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
|
||||
tmp->name_ = strings_.add(nex->name());
|
||||
nex->t_cookie(tmp);
|
||||
obj->pin_ = tmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
||||
|
|
@ -2180,6 +2179,11 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.132 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.131 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
41
t-dll.h
41
t-dll.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.115 2004/10/04 01:10:56 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.116 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -82,9 +82,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_mult(const NetMult*);
|
||||
void lpm_mux(const NetMux*);
|
||||
void lpm_ram_dq(const NetRamDq*);
|
||||
bool part_select(const NetPartSelect*);
|
||||
void net_assign(const NetAssign_*);
|
||||
bool net_cassign(const NetCAssign*);
|
||||
bool net_force(const NetForce*);
|
||||
bool net_function(const NetUserFunc*);
|
||||
bool net_const(const NetConst*);
|
||||
void net_probe(const NetEvProbe*);
|
||||
|
|
@ -162,6 +161,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
void add_root(ivl_design_s &des_, const NetScope *s);
|
||||
|
||||
void make_assign_lvals_(const NetAssignBase*net);
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
|
|
@ -344,9 +344,16 @@ struct ivl_lpm_s {
|
|||
struct ivl_lpm_arith_s {
|
||||
unsigned width;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t*q, *a, *b;
|
||||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_part_s {
|
||||
unsigned width;
|
||||
unsigned base;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, a;
|
||||
} part;
|
||||
|
||||
struct ivl_lpm_ufunc_s {
|
||||
ivl_scope_t def;
|
||||
unsigned ports;
|
||||
|
|
@ -395,10 +402,7 @@ struct ivl_net_const_s {
|
|||
char *bits_;
|
||||
} b;
|
||||
|
||||
union {
|
||||
ivl_nexus_t pin_;
|
||||
ivl_nexus_t*pins_;
|
||||
} n;
|
||||
ivl_nexus_t pin_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -407,6 +411,7 @@ struct ivl_net_const_s {
|
|||
*/
|
||||
struct ivl_net_logic_s {
|
||||
ivl_logic_t type_;
|
||||
unsigned width_;
|
||||
ivl_udp_t udp;
|
||||
|
||||
perm_string name_;
|
||||
|
|
@ -578,10 +583,7 @@ struct ivl_signal_s {
|
|||
perm_string name_;
|
||||
ivl_scope_t scope_;
|
||||
|
||||
union {
|
||||
ivl_nexus_t pin_;
|
||||
ivl_nexus_t*pins_;
|
||||
} n;
|
||||
ivl_nexus_t pin_;
|
||||
|
||||
struct ivl_attribute_s*attr;
|
||||
unsigned nattr;
|
||||
|
|
@ -595,7 +597,8 @@ struct ivl_signal_s {
|
|||
struct ivl_statement_s {
|
||||
enum ivl_statement_type_e type_;
|
||||
union {
|
||||
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB */
|
||||
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB
|
||||
IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
|
||||
unsigned lvals_;
|
||||
struct ivl_lval_s*lval_;
|
||||
ivl_expr_t rval_;
|
||||
|
|
@ -615,13 +618,6 @@ struct ivl_statement_s {
|
|||
struct ivl_statement_s*case_st;
|
||||
} case_;
|
||||
|
||||
struct { /* IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
|
||||
unsigned lvals;
|
||||
struct ivl_lval_s*lval;
|
||||
unsigned npins;
|
||||
ivl_nexus_t*pins;
|
||||
} cassign_;
|
||||
|
||||
struct { /* IVL_ST_CONDIT */
|
||||
/* This is the condition expression */
|
||||
ivl_expr_t cond_;
|
||||
|
|
@ -684,6 +680,11 @@ struct ivl_variable_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.116 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.115 2004/10/04 01:10:56 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
29
target.cc
29
target.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.70 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -137,20 +137,19 @@ void target_t::lpm_ram_dq(const NetRamDq*)
|
|||
"Unhandled NetRamDq." << endl;
|
||||
}
|
||||
|
||||
bool target_t::part_select(const NetPartSelect*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetPartSelect." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::net_case_cmp(const NetCaseCmp*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled case compare node." << endl;
|
||||
}
|
||||
|
||||
bool target_t::net_cassign(const NetCAssign*dev)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): ";
|
||||
cerr << dev->get_line();
|
||||
cerr << ": Target does not support procedural continuous assignment." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_const(const NetConst*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -158,13 +157,6 @@ bool target_t::net_const(const NetConst*)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_force(const NetForce*dev)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetForce node." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_function(const NetUserFunc*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -420,6 +412,11 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.70 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.69 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
11
target.h
11
target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.66 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -86,14 +86,14 @@ struct target_t {
|
|||
virtual void lpm_mux(const NetMux*);
|
||||
virtual void lpm_ram_dq(const NetRamDq*);
|
||||
|
||||
virtual bool part_select(const NetPartSelect*);
|
||||
|
||||
/* Output a gate (called for each gate) */
|
||||
virtual void logic(const NetLogic*);
|
||||
virtual bool bufz(const NetBUFZ*);
|
||||
virtual void udp(const NetUDP*);
|
||||
virtual void net_case_cmp(const NetCaseCmp*);
|
||||
virtual bool net_cassign(const NetCAssign*);
|
||||
virtual bool net_const(const NetConst*);
|
||||
virtual bool net_force(const NetForce*);
|
||||
virtual bool net_function(const NetUserFunc*);
|
||||
virtual void net_probe(const NetEvProbe*);
|
||||
|
||||
|
|
@ -170,6 +170,11 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.66 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.65 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
12
targets.cc
12
targets.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: targets.cc,v 1.11 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: targets.cc,v 1.12 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -25,17 +25,25 @@
|
|||
# include "target.h"
|
||||
|
||||
extern const struct target tgt_dll;
|
||||
#ifdef WITH_T_XNF
|
||||
extern const struct target tgt_xnf;
|
||||
|
||||
#endif
|
||||
|
||||
const struct target *target_table[] = {
|
||||
&tgt_dll,
|
||||
#ifdef WITH_T_XNF
|
||||
&tgt_xnf,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: targets.cc,v $
|
||||
* Revision 1.12 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.11 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
|
|
|||
166
tgt-stub/stub.c
166
tgt-stub/stub.c
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stub.c,v 1.90 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.91 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -184,6 +184,7 @@ static void show_expression(ivl_expr_t net, unsigned ind)
|
|||
static void show_lpm(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
ivl_nexus_t nex;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
|
|
@ -191,19 +192,11 @@ static void show_lpm(ivl_lpm_t net)
|
|||
case IVL_LPM_ADD: {
|
||||
fprintf(out, " LPM_ADD %s: <width=%u>\n",
|
||||
ivl_lpm_basename(net), width);
|
||||
for (idx = 0 ; idx < width ; idx += 1)
|
||||
fprintf(out, " Q %u: %s\n", idx,
|
||||
ivl_nexus_name(ivl_lpm_q(net, idx)));
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_data(net, idx);
|
||||
fprintf(out, " Data A %u: %s\n", idx,
|
||||
nex? ivl_nexus_name(nex) : "");
|
||||
}
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_datab(net, idx);
|
||||
fprintf(out, " Data B %u: %s\n", idx,
|
||||
nex? ivl_nexus_name(nex) : "");
|
||||
}
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(ivl_lpm_q(net, 0)));
|
||||
nex = ivl_lpm_data(net, 0);
|
||||
fprintf(out, " DataA: %s\n", nex? ivl_nexus_name(nex) : "");
|
||||
ivl_nexus_t nex = ivl_lpm_datab(net, 0);
|
||||
fprintf(out, " DataB: %s\n", nex? ivl_nexus_name(nex) : "");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -367,6 +360,15 @@ static void show_lpm(ivl_lpm_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
case IVL_LPM_PART: {
|
||||
fprintf(out, " LPM_PART %s: <width=%u, base=%u, signed=%d>\n",
|
||||
ivl_lpm_basename(net),
|
||||
width, ivl_lpm_base(net), ivl_lpm_signed(net));
|
||||
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
|
||||
fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n",
|
||||
ivl_lpm_type(net),
|
||||
|
|
@ -396,17 +398,13 @@ static void show_assign_lval(ivl_lval_t lval, unsigned ind)
|
|||
|
||||
} else {
|
||||
unsigned pp;
|
||||
ivl_nexus_t nex = ivl_lval_pin(lval, 0);
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig);
|
||||
|
||||
fprintf(out, "%*spart_off=%u {%s", ind, "",
|
||||
ivl_lval_part_off(lval),
|
||||
ivl_nexus_name(nex));
|
||||
fprintf(out, "<nptrs=%u>", ivl_nexus_ptrs(nex));
|
||||
for (pp = 1 ; pp < ivl_lval_pins(lval) ; pp += 1) {
|
||||
nex = ivl_lval_pin(lval, pp);
|
||||
fprintf(out, ", %s", ivl_nexus_name(nex));
|
||||
fprintf(out, "<nptrs=%u>", ivl_nexus_ptrs(nex));
|
||||
}
|
||||
fprintf(out, "}\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -481,6 +479,17 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
|||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_CASSIGN:
|
||||
fprintf(out, "%*sCONTINUOUS ASSIGN <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
||||
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
|
||||
if (ivl_stmt_rval(net))
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_ST_CONDIT: {
|
||||
ivl_expr_t ex = ivl_stmt_cond_expr(net);
|
||||
ivl_statement_t t = ivl_stmt_cond_true(net);
|
||||
|
|
@ -501,6 +510,15 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
|||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_DEASSIGN:
|
||||
fprintf(out, "%*sDEASSIGN <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
||||
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
|
||||
break;
|
||||
|
||||
case IVL_ST_DELAY:
|
||||
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
|
|
@ -656,7 +674,9 @@ static void show_event(ivl_event_t net)
|
|||
|
||||
static void show_signal(ivl_signal_t net)
|
||||
{
|
||||
unsigned pin;
|
||||
unsigned idx;
|
||||
ivl_nexus_t nex;
|
||||
|
||||
const char*type = "?";
|
||||
const char*port = "";
|
||||
const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";
|
||||
|
|
@ -702,61 +722,60 @@ static void show_signal(ivl_signal_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
fprintf(out, " %s %s %s[%u] %s\n", type, sign, port,
|
||||
ivl_signal_pins(net), ivl_signal_basename(net));
|
||||
nex = ivl_signal_nex(net);
|
||||
|
||||
for (pin = 0 ; pin < ivl_signal_pins(net) ; pin += 1) {
|
||||
unsigned idx;
|
||||
ivl_nexus_t nex = ivl_signal_pin(net, pin);
|
||||
|
||||
fprintf(out, " [%u]: nexus=%s\n", pin, ivl_nexus_name(nex));
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_net_const_t con;
|
||||
ivl_net_logic_t log;
|
||||
ivl_lpm_t lpm;
|
||||
ivl_signal_t sig;
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
|
||||
|
||||
static const char* str_tab[8] = {
|
||||
"HiZ", "small", "medium", "weak",
|
||||
"large", "pull", "strong", "supply"};
|
||||
|
||||
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
|
||||
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
|
||||
|
||||
if ((sig = ivl_nexus_ptr_sig(ptr))) {
|
||||
fprintf(out, " %s[%u] (%s0, %s1)\n",
|
||||
ivl_signal_name(sig),
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
} else if ((log = ivl_nexus_ptr_log(ptr))) {
|
||||
fprintf(out, " %s[%u] (%s0, %s1)\n",
|
||||
ivl_logic_name(log),
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
|
||||
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
|
||||
ivl_scope_name(ivl_lpm_scope(lpm)),
|
||||
ivl_lpm_basename(lpm), dr0, dr1);
|
||||
|
||||
} else if ((con = ivl_nexus_ptr_con(ptr))) {
|
||||
const char*bits = ivl_const_bits(con);
|
||||
unsigned pin = ivl_nexus_ptr_pin(ptr);
|
||||
|
||||
fprintf(out, " const-%c (%s0, %s1)\n",
|
||||
bits[pin], dr0, dr1);
|
||||
fprintf(out, " %s %s %s[%d:%d] %s <width=%u> nexus=%s\n",
|
||||
type, sign, port,
|
||||
ivl_signal_msb(net), ivl_signal_lsb(net),
|
||||
ivl_signal_basename(net), ivl_signal_width(net),
|
||||
ivl_nexus_name(nex));
|
||||
|
||||
|
||||
} else {
|
||||
fprintf(out, " ?[%u] (%s0, %s1)\n",
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
}
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_net_const_t con;
|
||||
ivl_net_logic_t log;
|
||||
ivl_lpm_t lpm;
|
||||
ivl_signal_t sig;
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
|
||||
|
||||
static const char* str_tab[8] = {
|
||||
"HiZ", "small", "medium", "weak",
|
||||
"large", "pull", "strong", "supply"};
|
||||
|
||||
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
|
||||
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
|
||||
|
||||
if ((sig = ivl_nexus_ptr_sig(ptr))) {
|
||||
fprintf(out, " %s[%u] (%s0, %s1)\n",
|
||||
ivl_signal_name(sig),
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
} else if ((log = ivl_nexus_ptr_log(ptr))) {
|
||||
fprintf(out, " %s[%u] (%s0, %s1)\n",
|
||||
ivl_logic_name(log),
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
|
||||
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
|
||||
ivl_scope_name(ivl_lpm_scope(lpm)),
|
||||
ivl_lpm_basename(lpm), dr0, dr1);
|
||||
|
||||
} else if ((con = ivl_nexus_ptr_con(ptr))) {
|
||||
const char*bits = ivl_const_bits(con);
|
||||
unsigned pin = ivl_nexus_ptr_pin(ptr);
|
||||
|
||||
fprintf(out, " const-%c (%s0, %s1)\n",
|
||||
bits[pin], dr0, dr1);
|
||||
|
||||
|
||||
} else {
|
||||
fprintf(out, " ?[%u] (%s0, %s1)\n",
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
}
|
||||
}
|
||||
|
||||
for (pin = 0 ; pin < ivl_signal_attr_cnt(net) ; pin += 1) {
|
||||
ivl_attribute_t atr = ivl_signal_attr_val(net, pin);
|
||||
for (idx = 0 ; idx < ivl_signal_attr_cnt(net) ; idx += 1) {
|
||||
ivl_attribute_t atr = ivl_signal_attr_val(net, idx);
|
||||
|
||||
switch (atr->type) {
|
||||
case IVL_ATT_STR:
|
||||
|
|
@ -837,7 +856,7 @@ static void show_logic(ivl_net_logic_t net)
|
|||
fprintf(out, ", %s", ivl_nexus_name(nex));
|
||||
}
|
||||
|
||||
fprintf(out, ");\n");
|
||||
fprintf(out, "); <width=%u>\n", ivl_logic_width(net));
|
||||
|
||||
npins = ivl_logic_attr_cnt(net);
|
||||
for (idx = 0 ; idx < npins ; idx += 1) {
|
||||
|
|
@ -953,6 +972,11 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.91 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.90 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_vpi.c,v 1.9 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: draw_vpi.c,v 1.10 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -89,6 +89,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
break;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
#if 0
|
||||
/* If the signal node is narrower then the signal
|
||||
itself, then this is a part select so I'm going
|
||||
to need to evaluate the expression.
|
||||
|
|
@ -112,7 +113,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
#else
|
||||
continue;
|
||||
#endif
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
if (!ivl_expr_oper1(expr)) {
|
||||
|
|
@ -169,6 +172,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
/* If this is a part select, then the value was
|
||||
calculated above. Otherwise, just pass the
|
||||
signal. */
|
||||
#if 0
|
||||
if (ivl_expr_width(expr) !=
|
||||
ivl_signal_pins(ivl_expr_signal(expr))) {
|
||||
break;
|
||||
|
|
@ -182,6 +186,11 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
vvp_signal_label(ivl_expr_signal(expr)));
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
fprintf(vvp_out, ", V_%s",
|
||||
vvp_signal_label(ivl_expr_signal(expr)));
|
||||
continue;
|
||||
#endif
|
||||
|
||||
case IVL_EX_VARIABLE: {
|
||||
ivl_variable_t var = ivl_expr_variable(expr);
|
||||
|
|
@ -296,6 +305,11 @@ int draw_vpi_rfunc_call(ivl_expr_t fnet)
|
|||
|
||||
/*
|
||||
* $Log: draw_vpi.c,v $
|
||||
* Revision 1.10 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.9 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_expr.c,v 1.110 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: eval_expr.c,v 1.111 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -1464,22 +1464,12 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
|
|||
if (swid > res.wid)
|
||||
swid = res.wid;
|
||||
|
||||
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
||||
/* If this is a REG (a variable) then I can do a vector
|
||||
read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
|
||||
res.base, vvp_signal_label(sig), lsi, swid);
|
||||
|
||||
} else {
|
||||
/* Vector reads of nets do not in general work because
|
||||
they are not really functors but references to
|
||||
scattered functors. So generate an array of loads. */
|
||||
for (idx = 0 ; idx < swid ; idx += 1) {
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, vvp_signal_label(sig), idx+lsi);
|
||||
}
|
||||
}
|
||||
/* XXXX I forget how to do part selects here. */
|
||||
assert(lsi == 0);
|
||||
|
||||
/* If this is a REG (a variable) then I can do a vector read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
|
||||
res.base, vvp_signal_label(sig), swid);
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < res.wid) {
|
||||
|
|
@ -2139,6 +2129,11 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
|||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.111 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.110 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_priv.h,v 1.28 2004/01/20 21:00:47 steve Exp $"
|
||||
#ident "$Id: vvp_priv.h,v 1.29 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_config.h"
|
||||
|
|
@ -138,7 +138,7 @@ extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
|
|||
* Return the base of an allocated vector in the thread. The bits
|
||||
* are marked allocated in the process.
|
||||
*
|
||||
* clr_bector
|
||||
* clr_vector
|
||||
* Clear a vector previously allocated.
|
||||
*
|
||||
* The thread vector allocator also keeps a lookaside of expression
|
||||
|
|
@ -193,6 +193,11 @@ extern unsigned thread_count;
|
|||
|
||||
/*
|
||||
* $Log: vvp_priv.h,v $
|
||||
* Revision 1.29 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.28 2004/01/20 21:00:47 steve
|
||||
* Isolate configure from containing config.h
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_process.c,v 1.93 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.94 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -77,6 +77,9 @@ static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
|
|||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
|
||||
assert(idx == 0);
|
||||
assert(part_off == 0); // XXXX Forgot how to support part/bit writes.
|
||||
|
||||
if (ivl_lval_mux(lval)) {
|
||||
assert(wid == 1);
|
||||
if ((ivl_signal_pins(sig)-1) <= 0xffffU) {
|
||||
|
|
@ -92,13 +95,9 @@ static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
|
|||
vvp_signal_label(sig), bit);
|
||||
}
|
||||
|
||||
} else if (wid == 1) {
|
||||
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit);
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit, wid);
|
||||
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), bit, wid);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -142,9 +141,12 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned idx,
|
|||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
|
||||
assert(part_off == 0);
|
||||
assert(idx == 0);
|
||||
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n",
|
||||
vvp_signal_label(sig), part_off+idx, delay, bit);
|
||||
fprintf(vvp_out, " %%assign/v0 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), delay, bit);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -212,8 +214,8 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
|||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
if (bit_limit > ivl_lval_width(lval))
|
||||
bit_limit = ivl_lval_width(lval);
|
||||
|
||||
if (mem) {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
|
|
@ -223,10 +225,12 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
|||
set_to_memory(mem, idx, bidx);
|
||||
cur_rbit += 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
|
||||
set_to_memory(mem, idx, 0);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
unsigned bidx = res.base < 4
|
||||
|
|
@ -234,11 +238,6 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
|||
: (res.base+cur_rbit);
|
||||
set_to_lvariable(lval, 0, bidx, bit_limit);
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -317,8 +316,8 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
|||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
if (bit_limit > ivl_lval_width(lval))
|
||||
bit_limit = ivl_lval_width(lval);
|
||||
|
||||
if (mem) {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
|
|
@ -329,11 +328,28 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
|||
}
|
||||
|
||||
for (idx = bit_limit
|
||||
; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
; idx < ivl_lval_width(lval) ; idx += 1)
|
||||
set_to_memory(mem, idx, 0);
|
||||
|
||||
|
||||
} else {
|
||||
/* Here we have the case of a blocking
|
||||
assign of a number to a signal:
|
||||
|
||||
<sig> = NUMBER;
|
||||
|
||||
Collect the number value into thread
|
||||
bits, and use a %set/v to write the reg
|
||||
variable. */
|
||||
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
struct vector_info vect;
|
||||
vect.wid = ivl_lval_width(lval);
|
||||
vect.base = allocate_vector(vect.wid);
|
||||
|
||||
/* This loop makes the value into thread
|
||||
bits. Use the constant thread bits 0-3 to
|
||||
generate the values of the vector. */
|
||||
idx = 0;
|
||||
while (idx < bit_limit) {
|
||||
unsigned cnt = 1;
|
||||
|
|
@ -341,19 +357,19 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
|||
&& (bits[cur_rbit] == bits[cur_rbit+cnt]))
|
||||
cnt += 1;
|
||||
|
||||
set_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
cnt);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
vect.base+idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
cnt);
|
||||
|
||||
cur_rbit += cnt;
|
||||
idx += cnt;
|
||||
}
|
||||
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
}
|
||||
/* write out the value into the .var. */
|
||||
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), vect.base, vect.wid);
|
||||
clr_vector(vect);
|
||||
}
|
||||
|
||||
if (skip_set_flag) {
|
||||
|
|
@ -490,138 +506,6 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
del = 0;
|
||||
}
|
||||
|
||||
/* Handle the special case that the r-value is a constant. We
|
||||
can generate the %set statement directly, without any worry
|
||||
about generating code to evaluate the r-value expressions. */
|
||||
|
||||
if (ivl_expr_type(rval) == IVL_EX_NUMBER) {
|
||||
unsigned lidx;
|
||||
const char*bits = ivl_expr_bits(rval);
|
||||
unsigned wid = ivl_expr_width(rval);
|
||||
unsigned cur_rbit = 0;
|
||||
|
||||
if (del != 0)
|
||||
calculate_into_x1(del);
|
||||
|
||||
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
|
||||
unsigned skip_set = transient_id++;
|
||||
unsigned skip_set_flag = 0;
|
||||
unsigned idx;
|
||||
unsigned bit_limit = wid - cur_rbit;
|
||||
lval = ivl_stmt_lval(net, lidx);
|
||||
|
||||
/* If there is a mux for the lval, calculate the
|
||||
value and write it into index0. */
|
||||
if (ivl_lval_mux(lval)) {
|
||||
calculate_into_x0(ivl_lval_mux(lval));
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
mem = ivl_lval_mem(lval);
|
||||
if (mem) {
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
|
||||
if (mem) {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
assign_to_memory(mem, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay);
|
||||
cur_rbit += 1;
|
||||
}
|
||||
|
||||
for (idx = bit_limit
|
||||
; idx < ivl_lval_pins(lval)
|
||||
; idx += 1) {
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
}
|
||||
|
||||
} else if ((del == 0) && (bit_limit > 2)) {
|
||||
|
||||
/* We have a vector, but no runtime
|
||||
calculated delays, to try to use vector
|
||||
assign instructions. */
|
||||
idx = 0;
|
||||
while (idx < bit_limit) {
|
||||
unsigned wid = 0;
|
||||
|
||||
do {
|
||||
wid += 1;
|
||||
if ((idx + wid) == bit_limit)
|
||||
break;
|
||||
|
||||
} while (bits[cur_rbit] == bits[cur_rbit+wid]);
|
||||
|
||||
switch (wid) {
|
||||
case 1:
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
break;
|
||||
case 2:
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
assign_to_lvariable(lval, idx+1,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
break;
|
||||
default:
|
||||
assign_to_lvector(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
idx += wid;
|
||||
cur_rbit += wid;
|
||||
}
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned wid = ivl_lval_pins(lval) - bit_limit;
|
||||
assign_to_lvector(lval, bit_limit,
|
||||
0, delay, wid);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if (del != 0)
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
cur_rbit += 1;
|
||||
}
|
||||
|
||||
for (idx = bit_limit
|
||||
; idx < ivl_lval_pins(lval)
|
||||
; idx += 1) {
|
||||
if (del != 0)
|
||||
assign_to_lvariable(lval, idx, 0,
|
||||
1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, 0,
|
||||
delay, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
{ struct vector_info res = draw_eval_expr(rval, 0);
|
||||
unsigned wid = res.wid;
|
||||
|
|
@ -653,10 +537,10 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
if (bit_limit > ivl_lval_width(lval))
|
||||
bit_limit = ivl_lval_width(lval);
|
||||
|
||||
if ((bit_limit > 2) && (mem == 0) && (del == 0)) {
|
||||
if ((mem == 0) && (del == 0)) {
|
||||
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
|
|
@ -682,7 +566,7 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
}
|
||||
}
|
||||
|
||||
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
|
||||
for (idx = bit_limit; idx < ivl_lval_width(lval); idx += 1)
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
else if (del != 0)
|
||||
|
|
@ -939,8 +823,7 @@ static int show_stmt_cassign(ivl_statement_t net)
|
|||
{
|
||||
ivl_lval_t lval;
|
||||
ivl_signal_t lsig;
|
||||
unsigned idx;
|
||||
char*tmp_label;
|
||||
ivl_expr_t rval;
|
||||
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
|
|
@ -948,16 +831,22 @@ static int show_stmt_cassign(ivl_statement_t net)
|
|||
lsig = ivl_lval_sig(lval);
|
||||
assert(lsig != 0);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_signal_pins(lsig) == ivl_stmt_nexus_count(net));
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
||||
tmp_label = strdup(vvp_signal_label(lsig));
|
||||
for (idx = 0 ; idx < ivl_stmt_nexus_count(net) ; idx += 1) {
|
||||
fprintf(vvp_out, " %%cassign V_%s[%u], %s;\n",
|
||||
tmp_label, idx,
|
||||
draw_net_input(ivl_stmt_nexus(net, idx)));
|
||||
if ( (rval = ivl_stmt_rval(net)) ) {
|
||||
|
||||
struct vector_info rvec = draw_eval_expr(rval, STUFF_OK_47);
|
||||
fprintf(vvp_out, " %%cassign/v V_%s, %u, %u;\n",
|
||||
vvp_signal_label(lsig), rvec.base, rvec.wid);
|
||||
|
||||
} else {
|
||||
/* The statement nexus count is an obsolete concept.
|
||||
Should be 1. */
|
||||
assert(ivl_stmt_nexus_count(net) == 1);
|
||||
|
||||
fprintf(stderr, "XXXX tgt-vvp: forgot how to implement cassign\n");
|
||||
return -1;
|
||||
}
|
||||
free(tmp_label);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -976,10 +865,8 @@ static int show_stmt_deassign(ivl_statement_t net)
|
|||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
|
||||
fprintf(vvp_out, " %%deassign V_%s[%u], 1;\n",
|
||||
vvp_signal_label(lsig), idx);
|
||||
}
|
||||
fprintf(vvp_out, " %%deassign V_%s;\n", vvp_signal_label(lsig));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1113,7 +1000,7 @@ static int show_stmt_force(ivl_statement_t net)
|
|||
assert(lsig != 0);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
||||
#if 0
|
||||
force_functor_label += 1;
|
||||
tmp_label = strdup(vvp_signal_label(lsig));
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
|
||||
|
|
@ -1128,6 +1015,9 @@ static int show_stmt_force(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
|
||||
force_functor_label, idx);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "XXXX I forgot how to implement %%force\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1222,7 +1112,7 @@ static int show_stmt_release(ivl_statement_t net)
|
|||
done before we start. */
|
||||
if (ivl_stmt_lvals(net) == 0)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
|
||||
|
|
@ -1243,7 +1133,9 @@ static int show_stmt_release(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%release V_%s[%u];\n",
|
||||
vvp_signal_label(lsig), idx);
|
||||
}
|
||||
|
||||
#else
|
||||
fprintf(stderr, "XXXX I forgot how to implement %%release\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1626,6 +1518,11 @@ int draw_func_definition(ivl_scope_t scope)
|
|||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.94 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.93 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_scope.c,v 1.103 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.104 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -350,33 +350,53 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
|
||||
sptr = ivl_nexus_ptr_sig(nptr);
|
||||
if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
|
||||
sprintf(result, "V_%s[%u]", vvp_signal_label(sptr), nptr_pin);
|
||||
/* Input is a .var. Note that these devices have only
|
||||
exactly one pin (that carries a vector) so nptr_pin
|
||||
must be 0. */
|
||||
assert(nptr_pin == 0);
|
||||
sprintf(result, "V_%s", vvp_signal_label(sptr));
|
||||
return result;
|
||||
}
|
||||
|
||||
cptr = ivl_nexus_ptr_con(nptr);
|
||||
if (cptr) {
|
||||
/* Constants should have exactly 1 pin, with a vector
|
||||
result. */
|
||||
assert(nptr_pin == 0);
|
||||
const char*bits = ivl_const_bits(cptr);
|
||||
ivl_drive_t drive;
|
||||
switch (bits[nptr_pin]) {
|
||||
case '0':
|
||||
drive = ivl_nexus_ptr_drive0(nptr);
|
||||
if (drive == IVL_DR_HiZ)
|
||||
sprintf(result, "C<z>");
|
||||
else
|
||||
sprintf(result, "C<%s0>", drive_string(drive));
|
||||
break;
|
||||
case '1':
|
||||
drive = ivl_nexus_ptr_drive1(nptr);
|
||||
if (drive == IVL_DR_HiZ)
|
||||
sprintf(result, "C<z>");
|
||||
else
|
||||
sprintf(result, "C<%s1>", drive_string(drive));
|
||||
break;
|
||||
default:
|
||||
sprintf(result, "C<%c>", bits[nptr_pin]);
|
||||
unsigned idx;
|
||||
|
||||
char*dp = result;
|
||||
strcpy(dp, "C4<");
|
||||
dp += strlen(dp);
|
||||
|
||||
for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
|
||||
switch (bits[ivl_const_width(cptr)-idx-1]) {
|
||||
case '0':
|
||||
drive = ivl_nexus_ptr_drive0(nptr);
|
||||
if (drive == IVL_DR_HiZ) {
|
||||
*dp++ = 'z';
|
||||
} else {
|
||||
*dp++ = '0';
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
drive = ivl_nexus_ptr_drive1(nptr);
|
||||
if (drive == IVL_DR_HiZ) {
|
||||
*dp++ = 'z';
|
||||
} else {
|
||||
*dp++ = '1';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*dp++ = bits[idx];
|
||||
break;
|
||||
}
|
||||
assert(dp - result < sizeof result);
|
||||
}
|
||||
|
||||
strcpy(dp, ">");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -403,11 +423,11 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_UFUNC:
|
||||
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
|
||||
if (ivl_lpm_q(lpm, idx) == nex) {
|
||||
sprintf(result, "L_%p[%u]", lpm, idx);
|
||||
return result;
|
||||
}
|
||||
case IVL_LPM_PART:
|
||||
if (ivl_lpm_q(lpm, 0) == nex) {
|
||||
sprintf(result, "L_%p", lpm);
|
||||
return result;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
|
@ -520,13 +540,13 @@ const char* draw_net_input(ivl_nexus_t nex)
|
|||
if (ndrivers == 0) {
|
||||
switch (res) {
|
||||
case IVL_SIT_TRI:
|
||||
nex_private = "C<z>";
|
||||
nex_private = "C4<z>";
|
||||
break;
|
||||
case IVL_SIT_TRI0:
|
||||
nex_private = "C<0>";
|
||||
nex_private = "C4<0>";
|
||||
break;
|
||||
case IVL_SIT_TRI1:
|
||||
nex_private = "C<1>";
|
||||
nex_private = "C4<1>";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -566,7 +586,7 @@ const char* draw_net_input(ivl_nexus_t nex)
|
|||
}
|
||||
}
|
||||
for ( ; idx < inst+4 ; idx += 1)
|
||||
fprintf(vvp_out, ", C<z>");
|
||||
fprintf(vvp_out, ", C4<z>");
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
|
@ -623,11 +643,10 @@ static void draw_reg_in_scope(ivl_signal_t sig)
|
|||
*/
|
||||
static void draw_net_in_scope(ivl_signal_t sig)
|
||||
{
|
||||
unsigned idx;
|
||||
int msb = ivl_signal_msb(sig);
|
||||
int lsb = ivl_signal_lsb(sig);
|
||||
typedef const char*const_charp;
|
||||
const_charp* args;
|
||||
const char* arg;
|
||||
|
||||
const char*signed_flag = ivl_signal_signed(sig)? "/s" : "";
|
||||
|
||||
|
|
@ -635,24 +654,16 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
|||
if (ivl_signal_local(sig))
|
||||
return;
|
||||
|
||||
args = (const_charp*)calloc(ivl_signal_pins(sig), sizeof(char*));
|
||||
|
||||
/* Connect all the pins of the signal to something. */
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_signal_pin(sig, idx);
|
||||
|
||||
args[idx] = draw_net_input(nex);
|
||||
/* Connect the pin of the signal to something. */
|
||||
{
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig);
|
||||
arg = draw_net_input(nex);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "V_%s .net%s \"%s\", %d, %d",
|
||||
fprintf(vvp_out, "V_%s .net%s \"%s\", %d, %d, %s;\n",
|
||||
vvp_signal_label(sig), signed_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
fprintf(vvp_out, ", %s", args[idx]);
|
||||
}
|
||||
fprintf(vvp_out, ";\n");
|
||||
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb, arg);
|
||||
|
||||
free(args);
|
||||
}
|
||||
|
||||
static void draw_delay(ivl_net_logic_t lptr)
|
||||
|
|
@ -939,7 +950,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
}
|
||||
}
|
||||
for ( ; pdx < inst+4 ; pdx += 1) {
|
||||
fprintf(vvp_out, ", C<%c>", identity_val);
|
||||
fprintf(vvp_out, ", C4<%c>", identity_val);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
|
|
@ -1137,25 +1148,35 @@ static void draw_lpm_arith_a_b_inputs(ivl_lpm_t net)
|
|||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t a = ivl_lpm_data(net, idx);
|
||||
if (a) {
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(a);
|
||||
} else {
|
||||
fprintf(vvp_out, ", C<0>");
|
||||
}
|
||||
|
||||
assert(width > 0);
|
||||
ivl_nexus_t nex = ivl_lpm_data(net, 0);
|
||||
ivl_signal_t sig = 0;
|
||||
|
||||
ivl_nexus_ptr_t np;
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
np = ivl_nexus_ptr(nex,idx);
|
||||
sig = ivl_nexus_ptr_sig(np);
|
||||
if (sig != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t b = ivl_lpm_datab(net, idx);
|
||||
if (b) {
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(b);
|
||||
} else {
|
||||
fprintf(vvp_out, ", C<0>");
|
||||
}
|
||||
assert(sig != 0);
|
||||
|
||||
fprintf(vvp_out, ", V_%s", vvp_signal_label(sig));
|
||||
|
||||
sig = 0;
|
||||
nex = ivl_lpm_datab(net, 0);
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
np = ivl_nexus_ptr(nex,idx);
|
||||
sig = ivl_nexus_ptr_sig(np);
|
||||
if (sig != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(sig != 0);
|
||||
|
||||
fprintf(vvp_out, ", V_%s", vvp_signal_label(sig));
|
||||
}
|
||||
|
||||
static void draw_lpm_add(ivl_lpm_t net)
|
||||
|
|
@ -1458,6 +1479,22 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
|
|||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a PART SELECT device. This has a single input and output.
|
||||
*/
|
||||
static void draw_lpm_part(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width, base;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
base = ivl_lpm_base(net);
|
||||
|
||||
fprintf(vvp_out, "L_%p .part ", net);
|
||||
draw_input_from_net(ivl_lpm_data(net, 0));
|
||||
|
||||
fprintf(vvp_out, ", %u, %u;\n", base, width);
|
||||
}
|
||||
|
||||
static void draw_lpm_in_scope(ivl_lpm_t net)
|
||||
{
|
||||
switch (ivl_lpm_type(net)) {
|
||||
|
|
@ -1474,6 +1511,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_add(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_PART:
|
||||
draw_lpm_part(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_NE:
|
||||
draw_lpm_eq(net);
|
||||
|
|
@ -1624,6 +1665,11 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.104 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.103 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.61 2004/10/04 01:09:52 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.62 2004/12/11 02:31:29 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -82,9 +82,10 @@ vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
|
|||
vpip_to_dec.o vpip_format.o vvp_vpi.o
|
||||
|
||||
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o \
|
||||
functor.o fvectors.o npmos.o resolv.o stop.o symbols.o ufunc.o codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o memory.o force.o event.o \
|
||||
logic.o delay.o words.o $V
|
||||
functor.o fvectors.o npmos.o part.o resolv.o stop.o symbols.o ufunc.o \
|
||||
codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \
|
||||
force.o event.o logic.o delay.o words.o $V
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
# Under Windows (mingw) I need to make the ivl.exe in two steps.
|
||||
|
|
|
|||
141
vvp/README.txt
141
vvp/README.txt
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: README.txt,v 1.47 2004/10/04 01:10:58 steve Exp $
|
||||
* $Id: README.txt,v 1.48 2004/12/11 02:31:29 steve Exp $
|
||||
*/
|
||||
|
||||
VVP SIMULATION ENGINE
|
||||
|
|
@ -241,31 +241,19 @@ A variable does not take inputs, since its value is set behaviorally
|
|||
by assignment events. It does have output, though, and its output is
|
||||
propagated into the net of functors in the usual way.
|
||||
|
||||
Therefore, the .var statement implicitly also creates .functors
|
||||
addressed by the label of the variable. It is in fact the functors
|
||||
that behavioral code reads when the value of the variable (or net) is
|
||||
read by behavioral code. If the .var represents a vector of .functors,
|
||||
the index of the LSB is always, from the perspective of vvp, ZERO. The
|
||||
<msb>,<lsb> details are there only for the benefit of VPI support.
|
||||
A variable gets its value by assignments from procedural code: %set
|
||||
and %assign. These instructions write values to the port-0 input. From
|
||||
there, the value is held.
|
||||
|
||||
The variable .functor implicitly has two inputs. The first is the
|
||||
value that gets set by assignments. The second input is connected to
|
||||
the driving expression of a procedural continuous assignments.
|
||||
Variable functors have an extra internal bit that tells if a
|
||||
procedural continuous assignment is active. The %cassign opcode
|
||||
connects and activates the procedural continuous assignment. The
|
||||
%deassign opcode disconnects and deactivates it.
|
||||
|
||||
The variable statement also creates a VPI object of the appropriate
|
||||
type. See the vpi.txt file for details about that object. The msb and
|
||||
lsb values are set from the parameters of the .var or .var/s, and the
|
||||
vpiReg is marked unsigned for .var, or signed for .var/s
|
||||
|
||||
Note that nets in a design do not necessarily have a specific functor
|
||||
or object allocated to them. Nets are just something that behavioral
|
||||
code can read, so it is enough to give to the behavioral code the
|
||||
vvp_ipoint_t object of the .functor that drives the net.
|
||||
Behavioral code can also invoke %cassign/v statements that work like
|
||||
%set/v, but instead write to port-1 of the variable node. Writes to
|
||||
port-1 of a variable activate continuous assign mode, where the values
|
||||
written to port-0 are ignored. The continuous assign mode remains
|
||||
active until a long(1) is written to port-3 (a command port).
|
||||
|
||||
Behavioral code may also invoke %force/v statements that write to port-2
|
||||
to invoke force mode. This overrides continuous assign mode until a
|
||||
long(2) is written to port-3 to disable force mode.
|
||||
|
||||
NET STATEMENTS:
|
||||
|
||||
|
|
@ -274,14 +262,21 @@ it (unless it uses a force) and it is given a different VPI type
|
|||
code. The syntax of a .net statement is also similar to but not
|
||||
exactly the same as the .var statement:
|
||||
|
||||
<label> .net "name", <msb>, <lsb>, <symbols_list>;
|
||||
<label> .net/s "name", <msb>, <lsb>, <symbols_list>;
|
||||
<label> .net "name", <msb>, <lsb>, <symbol>;
|
||||
<label> .net/s "name", <msb>, <lsb>, <symbol>;
|
||||
|
||||
Like a .var statement, the .net statement creates a VPI object with
|
||||
the basename and dimensions given as parameters, but unlike a .var
|
||||
statement, it creates no functors. The symbol list is a list of
|
||||
functors that feed into each bit of the vector, and the vpiHandle
|
||||
holds references to those functors that are fed it.
|
||||
the basename and dimensions given as parameters. The symbol is a
|
||||
functor that feeds into the vector of the net, and the vpiHandle
|
||||
holds references to that functor.
|
||||
|
||||
NOTE: Nets also, unlike .vars, should also have a way of getting
|
||||
at the strengths of each bit. I haven't worked out how that will
|
||||
happen, yet.
|
||||
|
||||
The input of a .net is replicated to its output. In this sense, it
|
||||
acts like a diode. The purpose of this node is to hold various VPI
|
||||
and event trappings.
|
||||
|
||||
The <label> is required and is used to locate the net object that is
|
||||
represents. This label does not map to a functor, so only references
|
||||
|
|
@ -443,7 +438,19 @@ resolution function.
|
|||
<label> .resolv tri1, <symbols_list>;
|
||||
|
||||
|
||||
FORCE STATEMENTS:
|
||||
PART SELECT STATEMENTS:
|
||||
|
||||
Part select statements are functors with three inputs. They take in at
|
||||
port-0 a vector, and output a selected (likely smaller) part of that
|
||||
vector. The other inputs specify what those parts are, as a cannonical
|
||||
bit number, and a width. Normally, those bits are constant values.
|
||||
|
||||
<label> .part <symbol>, <base>, <wid>;
|
||||
|
||||
The input is typically a .reg or .net, but can be any vector node in
|
||||
the netlist.
|
||||
|
||||
FORCE STATEMENTS (old method - remove me):
|
||||
|
||||
A force statement creates functors that represent a Verilog force
|
||||
statement.
|
||||
|
|
@ -465,33 +472,44 @@ To activate and deactivate a force on a single bit, use:
|
|||
<signal> is the label of the functor that drives the signal that is
|
||||
being forced.
|
||||
|
||||
FORCE STATEMENTS (new method - implement me):
|
||||
|
||||
A %force instruction, as described in the .var section, forces a
|
||||
constant value onto a .var or .net, and the matching %release release
|
||||
that value. However, there are times when the value of a functor
|
||||
(i.e. another .net) needs to be forced onto a .var or .net. For this
|
||||
task, the %force/link instruction exists:
|
||||
|
||||
%force/link <dst>, <src> ;
|
||||
%release/link <dst> ;
|
||||
|
||||
This causes the output of the node <src> to be linked to the force
|
||||
input of the <dst> .var/.net node. When linked, the output functor
|
||||
will automatically drive values to the force port of the destination
|
||||
node. The matching %release/link instruction removes the link (a
|
||||
%release is still needed) to the destination.
|
||||
|
||||
The instructions:
|
||||
|
||||
%cassign/link <dst>, <src> ;
|
||||
%deassign/link <dst> ;
|
||||
|
||||
are the same concept, but for the continuous assign port.
|
||||
|
||||
STRUCTURAL ARITHMETIC STATEMENTS:
|
||||
|
||||
The various Verilog arithmetic operators (+-*/%) are available to
|
||||
structural contexts even though they do not fit into nice neat
|
||||
functors. These operators are not in general bitwise, so special
|
||||
measures are needed to make them work in a functor environment. We
|
||||
create special statement types for the various arithmetic operators.
|
||||
The various Verilog arithmetic operators (+-*/%) ar avaiable to
|
||||
structural contexts as two-input functors that take in vectors. All of
|
||||
these operators take two inputs and generate a fixed width output. The
|
||||
input vectors will be padded if needed to get the desired output width.
|
||||
|
||||
<label> .arith/sub <wid>, <symbols_list>;
|
||||
<label> .arith/sum <wid>, <symbols_list>;
|
||||
<label> .arith/mult <wid>, <symbols_list>;
|
||||
<label> .arith/div <wid>, <symbols_list>;
|
||||
<label> .arith/mod <wid>, <symbols_list>;
|
||||
|
||||
Addition is represented by the .arith/sum statement. This creates an
|
||||
array of functors based at the label. The width of the array is given
|
||||
by <wid>, and the <symbols_list> connects the inputs.
|
||||
|
||||
The sum can add together up to 4 operands, specified in the
|
||||
<symbols_list> one bit at a time. All the bits of the first operand
|
||||
(lsb first) are listed, then the bits of the second, and so on. The
|
||||
number of symbols must be an even multiple of the width of the operator.
|
||||
|
||||
Subtraction is similar to addition, except that the 2nd, 3rd and 4th
|
||||
vectors are subtracted from the first.
|
||||
<label> .arith/sub <wid>, <A>, <B>;
|
||||
<label> .arith/sum <wid>, <A>, <B>;
|
||||
<label> .arith/mult <wid>, <A>, <B>;
|
||||
<label> .arith/div <wid>, <A>, <B>;
|
||||
<label> .arith/mod <wid>, <A>, <B>;
|
||||
|
||||
In all cases, there are no width limits, so long as the width is fixed.
|
||||
|
||||
STRUCTURAL COMPARE STATEMENTS:
|
||||
|
||||
|
|
@ -587,6 +605,23 @@ parent, and %end in the child. Without this proper matching, the
|
|||
hierarchical relationships can get confused. The behavior of erroneous
|
||||
code is undefined.
|
||||
|
||||
* Thread Context
|
||||
|
||||
The context of a thread is all the local data that only that thread
|
||||
can address. The local data is broken into two addresses spaces: bit
|
||||
memory and word memory.
|
||||
|
||||
The bit memory is a region of 4-value bits (0,1,x,z) that can be
|
||||
addressed in strips of arbitrary length. For example, an 8-bit value
|
||||
can be in locations 8 through and including 15. The bits at address 0,
|
||||
1, 2 and 3 are special constant values. Reads from those locations
|
||||
make vectors of 0, 1, x or z values, so these can be used to
|
||||
manufacture complex values elsewhere.
|
||||
|
||||
The word memory is a region of tagged words. The value in each word
|
||||
may be native long or real. These words have a distinct address space
|
||||
from the bits.
|
||||
|
||||
* Threads and scopes
|
||||
|
||||
The Verilog ``disable'' statement deserves some special mention
|
||||
|
|
|
|||
330
vvp/arith.cc
330
vvp/arith.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: arith.cc,v 1.30 2004/10/04 01:10:58 steve Exp $"
|
||||
#ident "$Id: arith.cc,v 1.31 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -30,57 +30,11 @@
|
|||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
void vvp_arith_::output_x_(vvp_ipoint_t base, bool push, unsigned val)
|
||||
vvp_arith_::vvp_arith_(unsigned wid)
|
||||
: wid_(wid), x_val_(wid)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(base,idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
|
||||
obj->put_oval(val, push);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_arith_::output_val_(vvp_ipoint_t base, bool push, unsigned long sum)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(base,idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
|
||||
unsigned val = sum & 1;
|
||||
sum >>= 1;
|
||||
|
||||
obj->put_oval(val, push);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the static sum_ scratch space is large enough for everybody
|
||||
|
||||
vvp_wide_arith_::vvp_wide_arith_(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
pagecount_ = (wid + pagesize - 1)/pagesize;
|
||||
sum_ = (unsigned long *)calloc(pagecount_, sizeof(unsigned long));
|
||||
assert(sum_);
|
||||
}
|
||||
|
||||
void vvp_wide_arith_::output_val_(vvp_ipoint_t base, bool push)
|
||||
{
|
||||
unsigned page = 0;
|
||||
unsigned pbit = 0;
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(base,idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
|
||||
unsigned val = (sum_[page] >> pbit) & 1;
|
||||
|
||||
pbit += 1;
|
||||
if (pbit == pagesize) {
|
||||
pbit = 0;
|
||||
page += 1;
|
||||
}
|
||||
|
||||
obj->put_oval(val, push);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
x_val_.set_bit(idx, BIT4_X);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -94,6 +48,7 @@ inline void vvp_arith_div::wide(vvp_ipoint_t base, bool push)
|
|||
|
||||
void vvp_arith_div::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
#if 0
|
||||
put(i, val);
|
||||
vvp_ipoint_t base = ipoint_make(i,0);
|
||||
|
||||
|
|
@ -146,6 +101,9 @@ void vvp_arith_div::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
result = 0 - result;
|
||||
|
||||
output_val_(base, push, result);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement vvp_arith_div::set\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void vvp_arith_mod::wide(vvp_ipoint_t base, bool push)
|
||||
|
|
@ -155,6 +113,7 @@ inline void vvp_arith_mod::wide(vvp_ipoint_t base, bool push)
|
|||
|
||||
void vvp_arith_mod::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
#if 0
|
||||
put(i, val);
|
||||
vvp_ipoint_t base = ipoint_make(i,0);
|
||||
|
||||
|
|
@ -187,12 +146,16 @@ void vvp_arith_mod::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
}
|
||||
|
||||
output_val_(base, push, a%b);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement vvp_arith_mod::set\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Multiplication
|
||||
|
||||
void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
#if 0
|
||||
put(i, val);
|
||||
vvp_ipoint_t base = ipoint_make(i,0);
|
||||
|
||||
|
|
@ -220,8 +183,12 @@ void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
}
|
||||
|
||||
output_val_(base, push, a*b);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement vvp_arith_mult::set\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
|
||||
{
|
||||
unsigned char *a, *b, *sum;
|
||||
|
|
@ -284,62 +251,67 @@ void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
|
|||
delete[]b;
|
||||
delete[]a;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Addition
|
||||
|
||||
void vvp_arith_sum::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
vvp_arith_sum::vvp_arith_sum(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
put(i, val);
|
||||
vvp_ipoint_t base = ipoint_make(i,0);
|
||||
}
|
||||
|
||||
unsigned page = 0;
|
||||
unsigned pbit = 0;
|
||||
unsigned long carry = 0;
|
||||
vvp_arith_sum::~vvp_arith_sum()
|
||||
{
|
||||
}
|
||||
|
||||
sum_[0] = 0;
|
||||
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||
{
|
||||
unsigned port = ptr.port();
|
||||
|
||||
switch (port) {
|
||||
case 0:
|
||||
op_a_ = bit;
|
||||
break;
|
||||
case 1:
|
||||
op_b_ = bit;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
|
||||
vvp_vector4_t value (wid_);
|
||||
|
||||
/* Pad input vectors with this value to widen to the desired
|
||||
output width. */
|
||||
const vvp_bit4_t pad = BIT4_0;
|
||||
|
||||
vvp_bit4_t carry = BIT4_0;
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(base, idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
|
||||
vvp_bit4_t b = (idx >= op_b_.size())? pad : op_b_.value(idx);
|
||||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
unsigned val = obj->ival;
|
||||
if (val & 0xaa) {
|
||||
output_x_(base, push);
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_);
|
||||
return;
|
||||
}
|
||||
|
||||
// Accumulate the sum of the input bits.
|
||||
unsigned long tmp = 0;
|
||||
if (val & 0x01)
|
||||
tmp += 1;
|
||||
if (val & 0x04)
|
||||
tmp += 1;
|
||||
if (val & 0x10)
|
||||
tmp += 1;
|
||||
if (val & 0x40)
|
||||
tmp += 1;
|
||||
|
||||
// Save carry bits
|
||||
if (pbit >= pagesize - 2)
|
||||
carry += (tmp + (sum_[page]>>pbit)) >> (pagesize-pbit);
|
||||
|
||||
// Put the next bits into the sum,
|
||||
sum_[page] += tmp << pbit;
|
||||
|
||||
pbit += 1;
|
||||
if (pbit >= pagesize) {
|
||||
pbit = 0;
|
||||
page += 1;
|
||||
if (page < pagecount_)
|
||||
sum_[page] = carry;
|
||||
carry = 0;
|
||||
}
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
output_val_(base, push);
|
||||
vvp_send_vec4(net->out, value);
|
||||
}
|
||||
|
||||
vvp_arith_sub::vvp_arith_sub(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_arith_sub::~vvp_arith_sub()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtraction works by adding the 2s complement of the B, C and D
|
||||
|
|
@ -347,67 +319,54 @@ void vvp_arith_sum::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
* plus one, so we further reduce the operation to adding in the
|
||||
* inverted value and adding a correction.
|
||||
*/
|
||||
void vvp_arith_sub::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||
{
|
||||
put(i, val);
|
||||
vvp_ipoint_t base = ipoint_make(i,0);
|
||||
unsigned port = ptr.port();
|
||||
|
||||
unsigned page = 0;
|
||||
unsigned pbit = 0;
|
||||
unsigned long carry = 0;
|
||||
switch (port) {
|
||||
case 0:
|
||||
op_a_ = bit;
|
||||
break;
|
||||
case 1:
|
||||
op_b_ = bit;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* There are 3 values subtracted from the first parameter, so
|
||||
there are three 2s complements, so three ~X +1. That's why
|
||||
the sum_ starts with 3. */
|
||||
sum_[0] = 3;
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
|
||||
vvp_vector4_t value (wid_);
|
||||
|
||||
/* Pad input vectors with this value to widen to the desired
|
||||
output width. */
|
||||
const vvp_bit4_t pad = BIT4_1;
|
||||
|
||||
vvp_bit4_t carry = BIT4_1;
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(base, idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
vvp_bit4_t a = (idx >= op_a_.size())? pad : op_a_.value(idx);
|
||||
vvp_bit4_t b = (idx >= op_b_.size())? pad : op_b_.value(idx);
|
||||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
unsigned val = obj->ival;
|
||||
if (val & 0xaa) {
|
||||
output_x_(base, push);
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_);
|
||||
return;
|
||||
}
|
||||
|
||||
// Accumulate the sum of the input bits. Add in the
|
||||
// first value, and the ones complement of the other values.
|
||||
unsigned long tmp = 0;
|
||||
if (val & 0x01)
|
||||
tmp += 1;
|
||||
if (! (val & 0x04))
|
||||
tmp += 1;
|
||||
if (! (val & 0x10))
|
||||
tmp += 1;
|
||||
if (! (val & 0x40))
|
||||
tmp += 1;
|
||||
|
||||
// Save carry bits
|
||||
if (pbit >= pagesize - 2)
|
||||
carry += (tmp + (sum_[page]>>pbit)) >> (pagesize-pbit);
|
||||
|
||||
// Put the next bits into the sum,
|
||||
sum_[page] += tmp << pbit;
|
||||
|
||||
pbit += 1;
|
||||
if (pbit >= pagesize) {
|
||||
pbit = 0;
|
||||
page += 1;
|
||||
if (page < pagecount_)
|
||||
sum_[page] = carry;
|
||||
carry = 0;
|
||||
}
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
output_val_(base, push);
|
||||
vvp_send_vec4(net->out, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
void vvp_cmp_eq::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
put(i, val);
|
||||
|
|
@ -436,12 +395,14 @@ void vvp_cmp_eq::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
|
||||
put_oval(out_val, push);
|
||||
}
|
||||
#endif
|
||||
|
||||
vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
void vvp_cmp_ne::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
put(i, val);
|
||||
|
|
@ -470,14 +431,14 @@ void vvp_cmp_ne::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
|
||||
put_oval(out_val, push);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
vvp_cmp_gtge_base_::vvp_cmp_gtge_base_(unsigned wid, bool flag)
|
||||
: vvp_arith_(wid), signed_flag_(flag)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i,
|
||||
bool push,
|
||||
unsigned val,
|
||||
|
|
@ -561,7 +522,7 @@ void vvp_cmp_gtge_base_::set_base(vvp_ipoint_t i,
|
|||
|
||||
put_oval(out_val, push);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
|
||||
|
|
@ -570,22 +531,26 @@ vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
|
|||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
void vvp_cmp_ge::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str)
|
||||
{
|
||||
set_base(i, push, val, str, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
|
||||
: vvp_cmp_gtge_base_(wid, flag)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
void vvp_cmp_gt::set(vvp_ipoint_t i, bool push, unsigned val, unsigned str)
|
||||
{
|
||||
set_base(i, push, val, str, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
put(i, val);
|
||||
|
|
@ -634,7 +599,9 @@ void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
||||
{
|
||||
put(i, val);
|
||||
|
|
@ -683,91 +650,14 @@ void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: arith.cc,v $
|
||||
* Revision 1.30 2004/10/04 01:10:58 steve
|
||||
* Clean up spurious trailing white space.
|
||||
* Revision 1.31 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.29 2004/09/22 16:44:07 steve
|
||||
* Fix LPM GE to match LPM GT behavior.
|
||||
*
|
||||
* Revision 1.28 2004/06/30 02:15:57 steve
|
||||
* Add signed LPM divide.
|
||||
*
|
||||
* Revision 1.27 2004/06/16 16:33:26 steve
|
||||
* Add structural equality compare nodes.
|
||||
*
|
||||
* Revision 1.26 2003/08/01 00:58:34 steve
|
||||
* Fix arithmetic operators in 64bit processors.
|
||||
*
|
||||
* Revision 1.25 2003/04/11 05:15:38 steve
|
||||
* Add signed versions of .cmp/gt/ge
|
||||
*
|
||||
* Revision 1.24 2002/08/12 01:35:07 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.23 2002/05/07 04:15:43 steve
|
||||
* Fix uninitialized memory accesses.
|
||||
*
|
||||
* Revision 1.22 2002/01/03 04:19:02 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
* Revision 1.21 2001/12/06 03:31:24 steve
|
||||
* Support functor delays for gates and UDP devices.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.20 2001/11/07 03:34:41 steve
|
||||
* Use functor pointers where vvp_ipoint_t is unneeded.
|
||||
*
|
||||
* Revision 1.19 2001/11/04 05:03:21 steve
|
||||
* MacOSX 10.1 updates.
|
||||
*
|
||||
* Revision 1.18 2001/10/31 04:27:46 steve
|
||||
* Rewrite the functor type to have fewer functor modes,
|
||||
* and use objects to manage the different types.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.17 2001/10/27 03:22:26 steve
|
||||
* Minor rework of summation carry propagation (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.16 2001/10/16 03:10:20 steve
|
||||
* Get Division error into the division method!
|
||||
*
|
||||
* Revision 1.15 2001/10/16 03:06:18 steve
|
||||
* Catch division by zero in .arith/div.
|
||||
*
|
||||
* Revision 1.14 2001/10/16 02:47:37 steve
|
||||
* Add arith/div object.
|
||||
*
|
||||
* Revision 1.13 2001/10/14 17:36:18 steve
|
||||
* Forgot to propagate carry.
|
||||
*
|
||||
* Revision 1.12 2001/10/14 16:36:43 steve
|
||||
* Very wide multiplication (Anthony Bybell)
|
||||
*
|
||||
* Revision 1.11 2001/07/13 00:38:57 steve
|
||||
* Remove width restriction on subtraction.
|
||||
*
|
||||
* Revision 1.10 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.9 2001/07/07 02:57:33 steve
|
||||
* Add the .shift/r functor.
|
||||
*
|
||||
* Revision 1.8 2001/07/06 04:46:44 steve
|
||||
* Add structural left shift (.shift/l)
|
||||
*
|
||||
* Revision 1.7 2001/06/29 01:21:48 steve
|
||||
* Relax limit on width of structural sum.
|
||||
*
|
||||
* Revision 1.6 2001/06/29 01:20:20 steve
|
||||
* Relax limit on width of structural sum.
|
||||
*
|
||||
* Revision 1.5 2001/06/16 23:45:05 steve
|
||||
* Add support for structural multiply in t-dll.
|
||||
* Add code generators and vvp support for both
|
||||
* structural and behavioral multiply.
|
||||
*/
|
||||
|
||||
|
|
|
|||
110
vvp/arith.h
110
vvp/arith.h
|
|
@ -19,38 +19,26 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: arith.h,v 1.19 2004/10/04 01:10:58 steve Exp $"
|
||||
#ident "$Id: arith.h,v 1.20 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
# include "vvp_net.h"
|
||||
|
||||
// base class for arithmetic functors
|
||||
|
||||
class vvp_arith_ : public functor_s {
|
||||
class vvp_arith_ : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
explicit vvp_arith_(unsigned wid) : wid_(wid) {};
|
||||
explicit vvp_arith_(unsigned wid);
|
||||
|
||||
protected:
|
||||
unsigned wid_;
|
||||
|
||||
protected:
|
||||
void output_x_(vvp_ipoint_t base, bool push, unsigned val = 2);
|
||||
void output_val_(vvp_ipoint_t base, bool push, unsigned long sum);
|
||||
};
|
||||
|
||||
// base class for wide arithmetic functors
|
||||
|
||||
class vvp_wide_arith_ : public vvp_arith_ {
|
||||
public:
|
||||
explicit vvp_wide_arith_(unsigned wid);
|
||||
|
||||
protected:
|
||||
static const unsigned pagesize = 8*sizeof(unsigned long);
|
||||
unsigned pagecount_;
|
||||
unsigned long *sum_;
|
||||
|
||||
void output_val_(vvp_ipoint_t base, bool push);
|
||||
vvp_vector4_t op_a_;
|
||||
vvp_vector4_t op_b_;
|
||||
// Precalculated X result for propagation.
|
||||
vvp_vector4_t x_val_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -89,20 +77,26 @@ class vvp_arith_mod : public vvp_arith_ {
|
|||
void wide(vvp_ipoint_t base, bool push);
|
||||
};
|
||||
|
||||
class vvp_arith_sum : public vvp_wide_arith_ {
|
||||
class vvp_arith_sum : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
explicit vvp_arith_sum(unsigned wid) : vvp_wide_arith_(wid) {}
|
||||
explicit vvp_arith_sum(unsigned wid);
|
||||
~vvp_arith_sum();
|
||||
|
||||
public:
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
|
||||
|
||||
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
};
|
||||
|
||||
class vvp_arith_sub : public vvp_wide_arith_ {
|
||||
class vvp_arith_sub : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
explicit vvp_arith_sub(unsigned wid) : vvp_wide_arith_(wid) {}
|
||||
explicit vvp_arith_sub(unsigned wid);
|
||||
~vvp_arith_sub();
|
||||
|
||||
public:
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
|
||||
|
||||
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
};
|
||||
|
||||
class vvp_cmp_eq : public vvp_arith_ {
|
||||
|
|
@ -169,66 +163,10 @@ class vvp_shiftr : public vvp_arith_ {
|
|||
|
||||
/*
|
||||
* $Log: arith.h,v $
|
||||
* Revision 1.19 2004/10/04 01:10:58 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.18 2004/09/22 16:44:07 steve
|
||||
* Fix LPM GE to match LPM GT behavior.
|
||||
*
|
||||
* Revision 1.17 2004/06/30 02:15:57 steve
|
||||
* Add signed LPM divide.
|
||||
*
|
||||
* Revision 1.16 2004/06/16 16:33:26 steve
|
||||
* Add structural equality compare nodes.
|
||||
*
|
||||
* Revision 1.15 2003/04/11 05:15:38 steve
|
||||
* Add signed versions of .cmp/gt/ge
|
||||
*
|
||||
* Revision 1.14 2002/08/12 01:35:07 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.13 2002/05/07 04:15:43 steve
|
||||
* Fix uninitialized memory accesses.
|
||||
*
|
||||
* Revision 1.12 2002/01/03 04:19:02 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
* Revision 1.11 2001/10/31 04:27:46 steve
|
||||
* Rewrite the functor type to have fewer functor modes,
|
||||
* and use objects to manage the different types.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.10 2001/10/27 03:22:26 steve
|
||||
* Minor rework of summation carry propagation (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.9 2001/10/16 02:47:37 steve
|
||||
* Add arith/div object.
|
||||
*
|
||||
* Revision 1.8 2001/07/13 00:38:57 steve
|
||||
* Remove width restriction on subtraction.
|
||||
*
|
||||
* Revision 1.7 2001/07/07 02:57:33 steve
|
||||
* Add the .shift/r functor.
|
||||
*
|
||||
* Revision 1.6 2001/07/06 04:46:44 steve
|
||||
* Add structural left shift (.shift/l)
|
||||
*
|
||||
* Revision 1.5 2001/06/29 01:20:20 steve
|
||||
* Relax limit on width of structural sum.
|
||||
*
|
||||
* Revision 1.4 2001/06/16 23:45:05 steve
|
||||
* Add support for structural multiply in t-dll.
|
||||
* Add code generators and vvp support for both
|
||||
* structural and behavioral multiply.
|
||||
*
|
||||
* Revision 1.3 2001/06/15 04:07:58 steve
|
||||
* Add .cmp statements for structural comparison.
|
||||
*
|
||||
* Revision 1.2 2001/06/07 03:09:03 steve
|
||||
* Implement .arith/sub subtraction.
|
||||
*
|
||||
* Revision 1.1 2001/06/05 03:05:41 steve
|
||||
* Add structural addition.
|
||||
* Revision 1.20 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
17
vvp/codes.h
17
vvp/codes.h
|
|
@ -19,11 +19,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: codes.h,v 1.66 2004/06/19 15:52:53 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.67 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pointers.h"
|
||||
# include "vvp_net.h"
|
||||
# include "memory.h"
|
||||
# include "vthread.h"
|
||||
|
||||
|
|
@ -39,7 +40,6 @@ extern bool of_ADD_WR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_ADDI(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_AND(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -47,7 +47,7 @@ extern bool of_ASSIGN_WR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_ASSIGN_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_BLEND(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CASSIGN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPS(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -78,7 +78,6 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -99,7 +98,6 @@ extern bool of_NORR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_OR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -133,7 +131,7 @@ struct vvp_code_s {
|
|||
|
||||
union {
|
||||
unsigned long number;
|
||||
vvp_ipoint_t iptr;
|
||||
vvp_net_t *net;
|
||||
vvp_code_t cptr;
|
||||
vvp_memory_t mem;
|
||||
struct __vpiHandle*handle;
|
||||
|
|
@ -143,7 +141,7 @@ struct vvp_code_s {
|
|||
|
||||
union {
|
||||
unsigned bit_idx[2];
|
||||
vvp_ipoint_t iptr2;
|
||||
vvp_net_t *net2;
|
||||
vvp_code_t cptr2;
|
||||
struct ufunc_core*ufunc_core_ptr;
|
||||
};
|
||||
|
|
@ -170,6 +168,11 @@ extern vvp_code_t codespace_null(void);
|
|||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.67 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.66 2004/06/19 15:52:53 steve
|
||||
* Add signed modulus operator.
|
||||
*
|
||||
|
|
|
|||
373
vvp/compile.cc
373
vvp/compile.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.cc,v 1.175 2004/10/04 01:10:58 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.176 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -88,7 +88,6 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
|
|
@ -96,7 +95,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cassign",of_CASSIGN,2, {OA_FUNC_PTR, OA_FUNC_PTR2,OA_NONE} },
|
||||
{ "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
|
|
@ -106,7 +105,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%deassign",of_DEASSIGN,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%deassign",of_DEASSIGN,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
@ -125,7 +124,6 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||
{ "%load/m", of_LOAD_MEM,2, {OA_BIT1, OA_MEM_PTR, OA_NONE} },
|
||||
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
|
||||
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
|
|
@ -146,7 +144,6 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%release",of_RELEASE,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/wr", of_SET_WORDR,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
||||
|
|
@ -213,21 +210,21 @@ static symbol_table_t sym_vpi = 0;
|
|||
* Add a functor to the symbol table
|
||||
*/
|
||||
|
||||
void define_functor_symbol(const char*label, vvp_ipoint_t ipt)
|
||||
void define_functor_symbol(const char*label, vvp_net_t*net)
|
||||
{
|
||||
symbol_value_t val;
|
||||
val.num = ipt;
|
||||
val.net = net;
|
||||
sym_set_value(sym_functors, label, val);
|
||||
}
|
||||
|
||||
static vvp_ipoint_t lookup_functor_symbol(const char*label)
|
||||
static vvp_net_t*lookup_functor_symbol(const char*label)
|
||||
{
|
||||
assert(sym_functors);
|
||||
symbol_value_t val = sym_get_value(sym_functors, label);
|
||||
return val.num;
|
||||
return val.net;
|
||||
}
|
||||
|
||||
static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
|
||||
static vvp_net_t* vvp_net_lookup(const char*label)
|
||||
{
|
||||
/* First, look to see if the symbol is a vpi object of some
|
||||
sort. If it is, then get the vvp_ipoint_t pointer out of
|
||||
|
|
@ -240,7 +237,7 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
|
|||
case vpiReg:
|
||||
case vpiIntegerVar: {
|
||||
__vpiSignal*sig = (__vpiSignal*)vpi;
|
||||
return vvp_fvector_get(sig->bits, idx);
|
||||
return sig->node;
|
||||
}
|
||||
|
||||
case vpiNamedEvent: {
|
||||
|
|
@ -253,10 +250,9 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Failing that, look for a general functor. */
|
||||
vvp_ipoint_t tmp = lookup_functor_symbol(label);
|
||||
if (tmp)
|
||||
tmp = ipoint_index(tmp, idx);
|
||||
vvp_net_t*tmp = lookup_functor_symbol(label);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -282,6 +278,7 @@ static vvp_ipoint_t ipoint_lookup(const char *label, unsigned idx)
|
|||
static struct resolv_list_s*resolv_list = 0;
|
||||
|
||||
struct resolv_list_s {
|
||||
virtual ~resolv_list_s() { }
|
||||
struct resolv_list_s*next;
|
||||
virtual bool resolve(bool mes = false) = 0;
|
||||
};
|
||||
|
|
@ -299,63 +296,64 @@ static void resolv_submit(struct resolv_list_s*cur)
|
|||
|
||||
|
||||
/*
|
||||
* And the application to functor input lookup
|
||||
* Look up vvp_nets in the symbol table. The "source" is the label for
|
||||
* the net that I want to feed, and net->port[port] is the vvp_net
|
||||
* input that I want that node to feed into. When the name is found,
|
||||
* put net->port[port] into the fan-out list for that node.
|
||||
*/
|
||||
|
||||
struct functor_resolv_list_s: public resolv_list_s {
|
||||
struct vvp_net_resolv_list_s: public resolv_list_s {
|
||||
// node to locate
|
||||
char*source;
|
||||
unsigned idx;
|
||||
vvp_ipoint_t port;
|
||||
// port to be driven by the located node.
|
||||
vvp_net_ptr_t port;
|
||||
virtual bool resolve(bool mes);
|
||||
};
|
||||
|
||||
bool functor_resolv_list_s::resolve(bool mes)
|
||||
bool vvp_net_resolv_list_s::resolve(bool mes)
|
||||
{
|
||||
vvp_ipoint_t tmp = ipoint_lookup(source, idx);
|
||||
vvp_net_t*tmp = vvp_net_lookup(source);
|
||||
|
||||
if (tmp) {
|
||||
functor_t fport = functor_index(tmp);
|
||||
functor_t iobj = functor_index(port);
|
||||
|
||||
iobj->port[ipoint_port(port)] = fport->out;
|
||||
fport->out = port;
|
||||
// Link the input port to the located output.
|
||||
vvp_net_t*net = port.ptr();
|
||||
net->port[port.port()] = tmp->out;
|
||||
tmp->out = port;
|
||||
|
||||
free(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mes)
|
||||
fprintf(stderr, "unresolved functor reference: %s\n", source);
|
||||
fprintf(stderr, "unresolved vvp_net reference: %s\n", source);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static
|
||||
void postpone_functor_input(vvp_ipoint_t ptr, char*lab, unsigned idx)
|
||||
void postpone_functor_input(vvp_net_ptr_t port, char*lab)
|
||||
{
|
||||
struct functor_resolv_list_s*res = new struct functor_resolv_list_s;
|
||||
struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s;
|
||||
|
||||
res->port = ptr;
|
||||
res->port = port;
|
||||
res->source = lab;
|
||||
res->idx = idx;
|
||||
|
||||
resolv_submit(res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generic functor reference lookup.
|
||||
*/
|
||||
|
||||
struct functor_gen_resolv_list_s: public resolv_list_s {
|
||||
char*source;
|
||||
unsigned idx;
|
||||
vvp_ipoint_t *ref;
|
||||
vvp_net_t**ref;
|
||||
virtual bool resolve(bool mes);
|
||||
};
|
||||
|
||||
bool functor_gen_resolv_list_s::resolve(bool mes)
|
||||
{
|
||||
vvp_ipoint_t tmp = ipoint_lookup(source, idx);
|
||||
vvp_net_t*tmp = vvp_net_lookup(source);
|
||||
|
||||
if (tmp) {
|
||||
*ref = tmp;
|
||||
|
|
@ -370,14 +368,13 @@ bool functor_gen_resolv_list_s::resolve(bool mes)
|
|||
return false;
|
||||
}
|
||||
|
||||
void functor_ref_lookup(vvp_ipoint_t *ref, char*lab, unsigned idx)
|
||||
void functor_ref_lookup(vvp_net_t**ref, char*lab)
|
||||
{
|
||||
struct functor_gen_resolv_list_s*res =
|
||||
new struct functor_gen_resolv_list_s;
|
||||
|
||||
res->ref = ref;
|
||||
res->source = lab;
|
||||
res->idx = idx;
|
||||
|
||||
resolv_submit(res);
|
||||
}
|
||||
|
|
@ -653,7 +650,7 @@ void compile_vpi_time_precision(long pre)
|
|||
}
|
||||
|
||||
/*
|
||||
* Run through the arguments looking for the functors that are
|
||||
* Run through the arguments looking for the nodes that are
|
||||
* connected to my input ports. For each source functor that I
|
||||
* find, connect the output of that functor to the indexed
|
||||
* input by inserting myself (complete with the port number in
|
||||
|
|
@ -666,53 +663,61 @@ void compile_vpi_time_precision(long pre)
|
|||
* and skip the symbol lookup.
|
||||
*/
|
||||
|
||||
void inputs_connect(vvp_ipoint_t fdx, unsigned argc, struct symb_s*argv)
|
||||
void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
||||
{
|
||||
vvp_net_ptr_t ifdx = vvp_net_ptr_t(fdx, port);
|
||||
char*tp;
|
||||
|
||||
/* Is this a vvp_vector4_t constant value? */
|
||||
if ((strncmp(label, "C4<", 3) == 0)
|
||||
&& ((tp = strchr(label,'>')))
|
||||
&& (tp[1] == 0)
|
||||
&& (strspn(label+3, "01xz") == (tp-label-3))) {
|
||||
|
||||
size_t v4size = tp-label-3;
|
||||
vvp_vector4_t tmp (v4size);
|
||||
|
||||
for (unsigned idx = 0 ; idx < v4size ; idx += 1) {
|
||||
vvp_bit4_t bit;
|
||||
switch (label[3+idx]) {
|
||||
case '0':
|
||||
bit = BIT4_0;
|
||||
break;
|
||||
case '1':
|
||||
bit = BIT4_1;
|
||||
break;
|
||||
case 'x':
|
||||
bit = BIT4_X;
|
||||
break;
|
||||
case 'z':
|
||||
bit = BIT4_Z;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
tmp.set_bit(v4size-idx-1, bit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ifdx, tmp);
|
||||
free(label);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the general case that this is a label for a node in
|
||||
the vvp net. This arranges for the label to be preserved in
|
||||
a linker list, and linked when the symbol table is
|
||||
complete. */
|
||||
postpone_functor_input(ifdx, label);
|
||||
}
|
||||
|
||||
void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert(argc <= 4);
|
||||
|
||||
for (unsigned idx = 0; idx < argc; idx += 1) {
|
||||
|
||||
/* Find the functor for this input. This assumes that
|
||||
wide (more then 4 inputs) gates are consecutive
|
||||
functors. */
|
||||
vvp_ipoint_t ifdx = ipoint_input_index(fdx, idx);
|
||||
functor_t iobj = functor_index(ifdx);
|
||||
|
||||
if (strcmp(argv[idx].text, "C<0>") == 0)
|
||||
iobj->set(ifdx, false, 0, St0);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<we0>") == 0)
|
||||
iobj->set(ifdx, false, 0, We0);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<pu0>") == 0)
|
||||
iobj->set(ifdx, false, 0, Pu0);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<su0>") == 0)
|
||||
iobj->set(ifdx, false, 0, Su0);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<1>") == 0)
|
||||
iobj->set(ifdx, false, 1, St1);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<we1>") == 0)
|
||||
iobj->set(ifdx, false, 1, We1);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<pu1>") == 0)
|
||||
iobj->set(ifdx, false, 1, Pu1);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<su1>") == 0)
|
||||
iobj->set(ifdx, false, 1, Su1);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<x>") == 0)
|
||||
iobj->set(ifdx, false, 2, StX);
|
||||
|
||||
else if (strcmp(argv[idx].text, "C<z>") == 0)
|
||||
iobj->set(ifdx, false, 3, HiZ);
|
||||
|
||||
else {
|
||||
postpone_functor_input(ifdx, argv[idx].text, argv[idx].idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
free(argv[idx].text);
|
||||
input_connect(fdx, idx, argv[idx].text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -731,7 +736,7 @@ void const_functor_s::set(vvp_ipoint_t p, bool, unsigned val, unsigned)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static vvp_ipoint_t make_const_functor(unsigned val,
|
||||
unsigned str0,
|
||||
unsigned str1)
|
||||
|
|
@ -744,9 +749,11 @@ static vvp_ipoint_t make_const_functor(unsigned val,
|
|||
|
||||
return fdx;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Lookup a functor[idx] and save the ipoint in *ref. */
|
||||
|
||||
#if 0
|
||||
static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
|
||||
{
|
||||
if (lab == 0)
|
||||
|
|
@ -786,10 +793,11 @@ static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
|
|||
functor_ref_lookup(ref, lab, idx);
|
||||
return;
|
||||
}
|
||||
|
||||
free(lab);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
|
||||
{
|
||||
for (unsigned i=1; i < wid; i++) {
|
||||
|
|
@ -799,33 +807,20 @@ static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
|
|||
fu->base_ = fdx;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void make_arith(vvp_arith_ *arith,
|
||||
char*label, long wid,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_ipoint_t fdx = functor_allocate(wid);
|
||||
functor_define(fdx, arith);
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
ptr->fun = arith;
|
||||
|
||||
define_functor_symbol(label, fdx);
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
make_extra_outputs(fdx, wid);
|
||||
|
||||
unsigned opcount = argc / wid;
|
||||
|
||||
struct symb_s tmp_argv[4];
|
||||
for (int idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(fdx,idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
|
||||
obj->ival = 0xaa >> 2*(4 - opcount);
|
||||
|
||||
for (unsigned cdx = 0 ; cdx < opcount ; cdx += 1)
|
||||
tmp_argv[cdx] = argv[idx + wid*cdx];
|
||||
|
||||
inputs_connect(ptr, opcount, tmp_argv);
|
||||
}
|
||||
assert(argc == 2);
|
||||
inputs_connect(ptr, argc, argv);
|
||||
|
||||
free(argv);
|
||||
}
|
||||
|
|
@ -904,21 +899,13 @@ void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|||
{
|
||||
assert( wid > 0 );
|
||||
|
||||
if ((argc % wid) != 0) {
|
||||
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label);
|
||||
compile_errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned opcount = argc / wid;
|
||||
if (opcount > 4) {
|
||||
fprintf(stderr, "%s; .arith has too many operands.\n", label);
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s .arith has wrong number of symbols\n", label);
|
||||
compile_errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_arith_ *arith = new vvp_arith_sum(wid);
|
||||
|
||||
make_arith(arith, label, wid, argc, argv);
|
||||
}
|
||||
|
||||
|
|
@ -988,6 +975,7 @@ static void make_shift(vvp_arith_*arith,
|
|||
char*label, long wid,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
#if 0
|
||||
vvp_ipoint_t fdx = functor_allocate(wid);
|
||||
functor_define(fdx, arith);
|
||||
|
||||
|
|
@ -1015,7 +1003,9 @@ static void make_shift(vvp_arith_*arith,
|
|||
|
||||
inputs_connect(ptr, tmp_argc, tmp_argv);
|
||||
}
|
||||
|
||||
#else
|
||||
fprintf(stderr, "XXXX make_shift not implemented\n");
|
||||
#endif
|
||||
free(argv);
|
||||
}
|
||||
|
||||
|
|
@ -1069,23 +1059,22 @@ void compile_shiftr(char*label, long wid, unsigned argc, struct symb_s*argv)
|
|||
void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert(argc <= 4);
|
||||
|
||||
functor_t obj = 0;
|
||||
vvp_net_fun_t* obj = 0;
|
||||
|
||||
if (strcmp(type,"tri") == 0) {
|
||||
obj = new resolv_functor_s(HiZ);
|
||||
obj = new resolv_functor(vvp_scaler_t(BIT4_Z, 0));
|
||||
|
||||
} else if (strcmp(type,"tri0") == 0) {
|
||||
obj = new resolv_functor_s(Pu0);
|
||||
obj = new resolv_functor(vvp_scaler_t(BIT4_0, 5));
|
||||
|
||||
} else if (strcmp(type,"tri1") == 0) {
|
||||
obj = new resolv_functor_s(Pu1);
|
||||
obj = new resolv_functor(vvp_scaler_t(BIT4_1, 5));
|
||||
|
||||
} else if (strcmp(type,"triand") == 0) {
|
||||
obj = new table_functor_s(ft_TRIAND, 6, 6);
|
||||
obj = new table_functor_s(ft_TRIAND);
|
||||
|
||||
} else if (strcmp(type,"trior") == 0) {
|
||||
obj = new table_functor_s(ft_TRIOR, 6, 6);
|
||||
obj = new table_functor_s(ft_TRIOR);
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "invalid resolver type: %s\n", type);
|
||||
|
|
@ -1093,13 +1082,10 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
|
|||
}
|
||||
|
||||
if (obj) {
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_define(fdx, obj);
|
||||
define_functor_symbol(label, fdx);
|
||||
|
||||
inputs_connect(fdx, argc, argv);
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
define_functor_symbol(label, net);
|
||||
inputs_connect(net, argc, argv);
|
||||
}
|
||||
|
||||
free(type);
|
||||
free(label);
|
||||
free(argv);
|
||||
|
|
@ -1108,6 +1094,7 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
|
|||
void compile_force(char*label, struct symb_s signal,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
#if 0
|
||||
vvp_ipoint_t ifofu = functor_allocate(argc);
|
||||
define_functor_symbol(label, ifofu);
|
||||
|
||||
|
|
@ -1121,7 +1108,9 @@ void compile_force(char*label, struct symb_s signal,
|
|||
// connect the force expression, one bit.
|
||||
inputs_connect(iobj, 1, &argv[i]);
|
||||
}
|
||||
|
||||
#else
|
||||
fprintf(stderr, "XXXX compile_force not implemented\n");
|
||||
#endif
|
||||
free(argv);
|
||||
free(signal.text);
|
||||
free(label);
|
||||
|
|
@ -1161,7 +1150,7 @@ void compile_udp_functor(char*label, char*type,
|
|||
{
|
||||
struct vvp_udp_s *u = udp_find(type);
|
||||
assert (argc == u->nin);
|
||||
|
||||
#if 0
|
||||
functor_t udp = new udp_functor_s(u);
|
||||
|
||||
unsigned nfun = (argc+3)/4;
|
||||
|
|
@ -1186,6 +1175,9 @@ void compile_udp_functor(char*label, char*type,
|
|||
|
||||
if (u->sequ)
|
||||
udp->put_oval(u->init, false);
|
||||
#else
|
||||
fprintf(stderr, "XXXX compile_udp_functor not implemented\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1207,6 +1199,7 @@ void compile_memory_port(char *label, char *memid,
|
|||
unsigned naddr,
|
||||
unsigned argc, struct symb_s *argv)
|
||||
{
|
||||
#if 0
|
||||
vvp_memory_t mem = memory_find(memid);
|
||||
free(memid);
|
||||
assert(mem);
|
||||
|
|
@ -1226,6 +1219,9 @@ void compile_memory_port(char *label, char *memid,
|
|||
|
||||
inputs_connect(ix, argc, argv);
|
||||
free(argv);
|
||||
#else
|
||||
fprintf(stderr, "XXXX compile_memory_port not implemented.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void compile_memory_init(char *memid, unsigned i, unsigned char val)
|
||||
|
|
@ -1322,9 +1318,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
|||
break;
|
||||
}
|
||||
|
||||
functor_ref_lookup(&code->iptr,
|
||||
opa->argv[idx].symb.text,
|
||||
opa->argv[idx].symb.idx);
|
||||
functor_ref_lookup(&code->net, opa->argv[idx].symb.text);
|
||||
break;
|
||||
|
||||
case OA_FUNC_PTR2:
|
||||
|
|
@ -1336,27 +1330,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
|||
break;
|
||||
}
|
||||
|
||||
if (strcmp(opa->argv[idx].symb.text, "C<0>") == 0) {
|
||||
code->iptr2 = ipoint_make(0, 0);
|
||||
free(opa->argv[idx].symb.text);
|
||||
|
||||
} else if (strcmp(opa->argv[idx].symb.text, "C<1>") == 0) {
|
||||
code->iptr2 = ipoint_make(0, 1);
|
||||
free(opa->argv[idx].symb.text);
|
||||
|
||||
} else if (strcmp(opa->argv[idx].symb.text, "C<x>") == 0) {
|
||||
code->iptr2 = ipoint_make(0, 2);
|
||||
free(opa->argv[idx].symb.text);
|
||||
|
||||
} else if (strcmp(opa->argv[idx].symb.text, "C<z>") == 0) {
|
||||
code->iptr2 = ipoint_make(0, 3);
|
||||
free(opa->argv[idx].symb.text);
|
||||
|
||||
} else {
|
||||
functor_ref_lookup(&code->iptr2,
|
||||
opa->argv[idx].symb.text,
|
||||
opa->argv[idx].symb.idx);
|
||||
}
|
||||
functor_ref_lookup(&code->net2, opa->argv[idx].symb.text);
|
||||
break;
|
||||
|
||||
case OA_NUMBER:
|
||||
|
|
@ -1519,20 +1493,15 @@ void compile_variable(char*label, char*name, int msb, int lsb,
|
|||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_ipoint_t fdx = functor_allocate(wid);
|
||||
define_functor_symbol(label, fdx);
|
||||
|
||||
functor_t fu = new var_functor_s [wid];
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
functor_define(ipoint_index(fdx, idx), fu+idx);
|
||||
}
|
||||
count_functors_var += wid;
|
||||
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
node->fun = vsig;
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vvp_fvector_t vec = vvp_fvector_continuous_new(wid, fdx);
|
||||
vpiHandle obj = (signed_flag > 1) ?
|
||||
vpip_make_int(name, msb, lsb, vec) :
|
||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, vec);
|
||||
vpip_make_int(name, msb, lsb, node) :
|
||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, node);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
|
|
@ -1540,23 +1509,35 @@ void compile_variable(char*label, char*name, int msb, int lsb,
|
|||
free(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we handle .net records from the vvp source:
|
||||
*
|
||||
* <label> .net <name>, <msb>, <lsb>, <input> ;
|
||||
* <label> .net/s <name>, <msb>, <lsb>, <input> ;
|
||||
*
|
||||
* Create a VPI handle to represent it, and fill that handle in with
|
||||
* references into the net.
|
||||
*/
|
||||
void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_fvector_t vec = vvp_fvector_new(wid);
|
||||
//define_fvector_symbol(label, vec);
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
assert(argc == wid);
|
||||
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
|
||||
node->fun = vsig;
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t *ref = vvp_fvector_member(vec, idx);
|
||||
functor_reference(ref, argv[idx].text, argv[idx].idx);
|
||||
}
|
||||
/* Add the label into the functor symbol table. */
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
assert(argc == 1);
|
||||
|
||||
/* Connect the source to my input. */
|
||||
inputs_connect(node, 1, argv);
|
||||
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vpiHandle obj = vpip_make_net(name, msb, lsb, signed_flag, vec);
|
||||
vpiHandle obj = vpip_make_net(name, msb, lsb, signed_flag, node);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
|
|
@ -1579,52 +1560,10 @@ void compile_param_string(char*label, char*name, char*str, char*value)
|
|||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.175 2004/10/04 01:10:58 steve
|
||||
* Clean up spurious trailing white space.
|
||||
* Revision 1.176 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.174 2004/06/30 02:15:57 steve
|
||||
* Add signed LPM divide.
|
||||
*
|
||||
* Revision 1.173 2004/06/19 15:52:53 steve
|
||||
* Add signed modulus operator.
|
||||
*
|
||||
* Revision 1.172 2004/06/16 16:33:26 steve
|
||||
* Add structural equality compare nodes.
|
||||
*
|
||||
* Revision 1.171 2004/05/19 03:26:24 steve
|
||||
* Support delayed/non-blocking assignment to reals and others.
|
||||
*
|
||||
* Revision 1.170 2003/09/04 20:26:31 steve
|
||||
* Add $push flag for threads.
|
||||
*
|
||||
* Revision 1.169 2003/07/30 01:13:28 steve
|
||||
* Add support for triand and trior.
|
||||
*
|
||||
* Revision 1.168 2003/07/22 20:30:24 steve
|
||||
* Forgot to read the /x parameter for %load/x
|
||||
*
|
||||
* Revision 1.167 2003/07/03 20:03:36 steve
|
||||
* Remove the vvp_cpoint_t indirect code pointer.
|
||||
*
|
||||
* Revision 1.166 2003/06/18 03:55:19 steve
|
||||
* Add arithmetic shift operators.
|
||||
*
|
||||
* Revision 1.165 2003/06/17 19:17:42 steve
|
||||
* Remove short int restrictions from vvp opcodes.
|
||||
*
|
||||
* Revision 1.164 2003/05/26 04:44:54 steve
|
||||
* Add the set/x0/x instruction.
|
||||
*
|
||||
* Revision 1.163 2003/05/25 03:04:55 steve
|
||||
* Useless cast.
|
||||
*
|
||||
* Revision 1.162 2003/05/24 02:48:37 steve
|
||||
* More thorough overflow error message.
|
||||
*
|
||||
* Revision 1.161 2003/05/23 03:44:34 steve
|
||||
* Assert that parameters fix into opcode.
|
||||
*
|
||||
* Revision 1.160 2003/04/23 03:09:25 steve
|
||||
* VPI Access to named events.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.h,v 1.56 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.57 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include "parse_misc.h"
|
||||
# include "vpi_user.h"
|
||||
# include "vvp_net.h"
|
||||
|
||||
/*
|
||||
* The functions described here are the compile time support
|
||||
|
|
@ -45,13 +46,13 @@ extern bool verbose_flag;
|
|||
* Connect a list of symbols to a contiguous set of ipoints.
|
||||
* Constants C<?> are handled by setting the ival of the ipoint.
|
||||
*/
|
||||
extern void inputs_connect(vvp_ipoint_t fdx, unsigned argc, struct symb_s*argv);
|
||||
extern void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv);
|
||||
extern void input_connect(vvp_net_t*fdx, unsigned port, char*label);
|
||||
|
||||
/*
|
||||
* Add a functor to the symbol table
|
||||
*/
|
||||
extern void define_functor_symbol(const char*label, vvp_ipoint_t ipt);
|
||||
|
||||
extern void define_functor_symbol(const char*label, vvp_net_t*ipt);
|
||||
|
||||
/*
|
||||
* This is a count of errors encountered during compilation. If this
|
||||
|
|
@ -87,6 +88,9 @@ extern void compile_functor(char*label, char*type,
|
|||
extern void compile_resolver(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_part_select(char*label, char*src,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
/*
|
||||
* This is called by the parser to make force functors.
|
||||
*/
|
||||
|
|
@ -268,6 +272,11 @@ extern void compile_net(char*label, char*name,
|
|||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.57 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.56 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
203
vvp/event.cc
203
vvp/event.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: event.cc,v 1.14 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: event.cc,v 1.15 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "event.h"
|
||||
|
|
@ -33,87 +33,56 @@
|
|||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
event_functor_s::event_functor_s(edge_t e)
|
||||
: edge(e)
|
||||
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
|
||||
{
|
||||
return 1 << ((from << 2) | to);
|
||||
}
|
||||
|
||||
const vvp_fun_edge::edge_t vvp_edge_posedge
|
||||
= VVP_EDGE(BIT4_0,BIT4_1)
|
||||
| VVP_EDGE(BIT4_0,BIT4_X)
|
||||
| VVP_EDGE(BIT4_0,BIT4_Z)
|
||||
| VVP_EDGE(BIT4_X,BIT4_1)
|
||||
| VVP_EDGE(BIT4_Z,BIT4_1)
|
||||
;
|
||||
|
||||
const vvp_fun_edge::edge_t vvp_edge_negedge
|
||||
= VVP_EDGE(BIT4_1,BIT4_0)
|
||||
| VVP_EDGE(BIT4_1,BIT4_X)
|
||||
| VVP_EDGE(BIT4_1,BIT4_Z)
|
||||
| VVP_EDGE(BIT4_X,BIT4_0)
|
||||
| VVP_EDGE(BIT4_Z,BIT4_0)
|
||||
;
|
||||
|
||||
const vvp_fun_edge::edge_t vvp_edge_anyedge = 0x7bde;
|
||||
const vvp_fun_edge::edge_t vvp_edge_none = 0;
|
||||
|
||||
vvp_fun_edge::vvp_fun_edge(edge_t e)
|
||||
: edge_(e)
|
||||
{
|
||||
threads = 0;
|
||||
}
|
||||
|
||||
event_functor_s::~event_functor_s()
|
||||
{}
|
||||
|
||||
/*
|
||||
* Receive a value into an event functor, whether an edge or event/or.
|
||||
* Detect edges, if any, then schedule awakened threads.
|
||||
*/
|
||||
void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
|
||||
{
|
||||
old_ival = ival;
|
||||
put(ptr, val);
|
||||
/* Only go through the effort if there is someone interested
|
||||
in the results... */
|
||||
if (threads || out) {
|
||||
|
||||
bool edge_p = true;
|
||||
|
||||
/* If there is an edge detect lookup table, then use the
|
||||
old input and new input to detect whether this is the
|
||||
requested edge. If there is no edge table, then any
|
||||
set is a match. */
|
||||
if (edge) {
|
||||
|
||||
unsigned pp = ipoint_port(ptr);
|
||||
|
||||
unsigned oval = (old_ival >> 2*pp) & 3;
|
||||
unsigned nval = (ival >> 2*pp) & 3;
|
||||
edge_p = edge & VVP_EDGE(oval,nval);
|
||||
}
|
||||
|
||||
/* If we detect an edge, then schedule any threads that
|
||||
are attached to this event, then propagate the
|
||||
positive detect to the output.
|
||||
|
||||
Note that only other events (notably event/or
|
||||
functors) can be connected to event outputs. */
|
||||
|
||||
if (edge_p) {
|
||||
vthread_t tmp = threads;
|
||||
threads = 0;
|
||||
vthread_schedule_list(tmp);
|
||||
|
||||
if (out) {
|
||||
functor_set(out, 0, St0, true);
|
||||
}
|
||||
// only one output? Why not propagate?
|
||||
//schedule_assign(out, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
named_event_functor_s::named_event_functor_s()
|
||||
{
|
||||
threads = 0;
|
||||
}
|
||||
|
||||
named_event_functor_s::~named_event_functor_s()
|
||||
vvp_fun_edge::~vvp_fun_edge()
|
||||
{
|
||||
}
|
||||
|
||||
void named_event_functor_s::set(vvp_ipoint_t ptr, bool push,
|
||||
unsigned val, unsigned str)
|
||||
void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
|
||||
{
|
||||
put(ptr, val);
|
||||
// XXXX for now, only support first port.
|
||||
assert(port.port() == 0);
|
||||
|
||||
if (threads) {
|
||||
/* See what kind of edge this represents. */
|
||||
edge_t mask = VVP_EDGE(bits_.value(0), bit.value(0));
|
||||
|
||||
/* Save the current input for the next time around. */
|
||||
bits_ = bit;
|
||||
|
||||
if (threads && (edge_ & mask)) {
|
||||
vthread_t tmp = threads;
|
||||
threads = 0;
|
||||
vthread_schedule_list(tmp);
|
||||
}
|
||||
|
||||
vpip_run_named_event_callbacks(handle);
|
||||
|
||||
/* This event may nest, so progagate if I have an output. */
|
||||
if (out) functor_set(out, 0, St0, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -127,9 +96,9 @@ void named_event_functor_s::set(vvp_ipoint_t ptr, bool push,
|
|||
void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
event_functor_s::edge_t edge = vvp_edge_none;
|
||||
vvp_fun_edge::edge_t edge = vvp_edge_none;
|
||||
|
||||
if (argc && type) {
|
||||
if (type) {
|
||||
if (strcmp(type,"posedge") == 0)
|
||||
edge = vvp_edge_posedge;
|
||||
else if (strcmp(type,"negedge") == 0)
|
||||
|
|
@ -137,37 +106,19 @@ void compile_event(char*label, char*type,
|
|||
else if (strcmp(type,"edge") == 0)
|
||||
edge = vvp_edge_anyedge;
|
||||
|
||||
assert(argc <= 4 || edge == vvp_edge_none);
|
||||
assert(argc <= 4);
|
||||
free(type);
|
||||
}
|
||||
|
||||
free(type);
|
||||
vvp_fun_edge*fun = new vvp_fun_edge(edge);
|
||||
|
||||
functor_t obj = new event_functor_s(edge);
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
ptr->fun = fun;
|
||||
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_define(fdx, obj);
|
||||
define_functor_symbol(label, fdx);
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
/* Run through the arguments looking for the functors that are
|
||||
connected to my input ports. For each source functor that I
|
||||
find, connect the output of that functor to the indexed
|
||||
input by inserting myself (complete with the port number in
|
||||
the vvp_ipoint_t) into the list that the source heads.
|
||||
|
||||
If the source functor is not declared yet, then don't do
|
||||
the link yet. Save the reference to be resolved later. */
|
||||
|
||||
if (edge != vvp_edge_none)
|
||||
inputs_connect(fdx, argc, argv);
|
||||
else
|
||||
// Are we sure that we have those .event/or
|
||||
// drivers exclusively?
|
||||
for (unsigned i=0; i<argc; i++) {
|
||||
inputs_connect(fdx, 1, argv+i);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
inputs_connect(ptr, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -177,17 +128,12 @@ void compile_event(char*label, char*type,
|
|||
*/
|
||||
void compile_named_event(char*label, char*name)
|
||||
{
|
||||
named_event_functor_s* fp = new named_event_functor_s;
|
||||
fprintf(stderr, "XXXX compile_named_event not implemented\n");
|
||||
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_define(fdx, fp);
|
||||
vvp_net_t*fdx = 0;
|
||||
|
||||
vpiHandle obj = vpip_make_named_event(name, fdx);
|
||||
|
||||
/* The event needs a back pointer so that triggers to the
|
||||
event functor (%set) can access the callbacks. */
|
||||
fp->handle = obj;
|
||||
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
|
|
@ -197,52 +143,9 @@ void compile_named_event(char*label, char*name)
|
|||
|
||||
/*
|
||||
* $Log: event.cc,v $
|
||||
* Revision 1.14 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.13 2003/11/26 01:47:18 steve
|
||||
* Propagate named event outputs, if any.
|
||||
*
|
||||
* Revision 1.12 2003/04/23 03:09:25 steve
|
||||
* VPI Access to named events.
|
||||
*
|
||||
* Revision 1.11 2003/01/06 23:57:26 steve
|
||||
* Schedule wait lists of threads as a single event,
|
||||
* to save on events. Also, improve efficiency of
|
||||
* event_s allocation. Add some event statistics to
|
||||
* get an idea where performance is really going.
|
||||
*
|
||||
* Revision 1.10 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.9 2002/07/17 18:30:01 steve
|
||||
* Fix uninitialized thread pointer in named event.
|
||||
*
|
||||
* Revision 1.8 2002/07/05 17:14:15 steve
|
||||
* Names of vpi objects allocated as vpip_strings.
|
||||
*
|
||||
* Revision 1.7 2002/05/19 05:18:16 steve
|
||||
* Add callbacks for vpiNamedEvent objects.
|
||||
*
|
||||
* Revision 1.6 2002/05/18 02:34:11 steve
|
||||
* Add vpi support for named events.
|
||||
*
|
||||
* Add vpi_mode_flag to track the mode of the
|
||||
* vpi engine. This is for error checking.
|
||||
*
|
||||
* Revision 1.5 2002/03/17 03:24:34 steve
|
||||
* Clean up edge detection code.
|
||||
*
|
||||
* Revision 1.4 2002/01/24 04:17:46 steve
|
||||
* Spelling in comment.
|
||||
*
|
||||
* Revision 1.3 2001/12/29 23:59:06 steve
|
||||
* push events through event/or lists.
|
||||
*
|
||||
* Revision 1.2 2001/11/16 04:22:27 steve
|
||||
* include stdlib.h for portability.
|
||||
*
|
||||
* Revision 1.1 2001/11/06 03:07:22 steve
|
||||
* Code rearrange. (Stephan Boettcher)
|
||||
* Revision 1.15 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
62
vvp/event.h
62
vvp/event.h
|
|
@ -19,44 +19,50 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: event.h,v 1.5 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: event.h,v 1.6 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
# include "vvp_net.h"
|
||||
# include "pointers.h"
|
||||
|
||||
/*
|
||||
* Event / edge detection functors
|
||||
*/
|
||||
|
||||
struct event_functor_s: public edge_inputs_functor_s, public waitable_hooks_s {
|
||||
typedef unsigned short edge_t;
|
||||
explicit event_functor_s(edge_t e);
|
||||
virtual ~event_functor_s();
|
||||
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
edge_t edge;
|
||||
/*
|
||||
* A "waitable" functor is one that the %wait instruction can wait
|
||||
* on. This includes the infrastructure needed to hold threads.
|
||||
*/
|
||||
struct waitable_hooks_s {
|
||||
vthread_t threads;
|
||||
};
|
||||
|
||||
#define VVP_EDGE(a,b) (1<<(((a)<<2)|(b)))
|
||||
/*
|
||||
* The vvp_fun_edge functor detects events that are edges of various
|
||||
* types. This should be hooked to a vvp_net_t that is connected to
|
||||
* the output of a signal that we wish to watch for edges.
|
||||
*/
|
||||
class vvp_fun_edge : public vvp_net_fun_t, public waitable_hooks_s {
|
||||
|
||||
const event_functor_s::edge_t vvp_edge_posedge
|
||||
= VVP_EDGE(0,1)
|
||||
| VVP_EDGE(0,2)
|
||||
| VVP_EDGE(0,3)
|
||||
| VVP_EDGE(2,1)
|
||||
| VVP_EDGE(3,1)
|
||||
;
|
||||
public:
|
||||
typedef unsigned short edge_t;
|
||||
explicit vvp_fun_edge(edge_t e);
|
||||
|
||||
const event_functor_s::edge_t vvp_edge_negedge
|
||||
= VVP_EDGE(1,0)
|
||||
| VVP_EDGE(1,2)
|
||||
| VVP_EDGE(1,3)
|
||||
| VVP_EDGE(2,0)
|
||||
| VVP_EDGE(3,0)
|
||||
;
|
||||
virtual ~vvp_fun_edge();
|
||||
|
||||
const event_functor_s::edge_t vvp_edge_anyedge = 0x7bde;
|
||||
const event_functor_s::edge_t vvp_edge_none = 0;
|
||||
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
|
||||
|
||||
private:
|
||||
vvp_vector4_t bits_;
|
||||
edge_t edge_;
|
||||
};
|
||||
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_posedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_negedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_anyedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_none;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This is a functor to represent named events. This functor has no
|
||||
* inputs, and no output. It is a functor so that the %wait and %set
|
||||
|
|
@ -77,9 +83,15 @@ struct named_event_functor_s : public waitable_hooks_s, public functor_s {
|
|||
*/
|
||||
struct callback_functor_s *vvp_fvector_make_callback
|
||||
(vvp_fvector_t, event_functor_s::edge_t = vvp_edge_none);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: event.h,v $
|
||||
* Revision 1.6 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.5 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
92
vvp/force.cc
92
vvp/force.cc
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: force.cc,v 1.8 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: force.cc,v 1.9 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "codes.h"
|
||||
|
|
@ -104,6 +104,7 @@ static bool release_force(vvp_ipoint_t itgt, functor_t tgt)
|
|||
*/
|
||||
bool of_FORCE(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
unsigned wid = cp->bit_idx[0];
|
||||
|
||||
for (unsigned i=0; i<wid; i++) {
|
||||
|
|
@ -141,7 +142,9 @@ bool of_FORCE(vthread_t thr, vvp_code_t cp)
|
|||
// on its forced value.
|
||||
fofu->set(ifofu, false, fofu->get_oval(), fofu->get_ostr());
|
||||
}
|
||||
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement %%force\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -151,12 +154,15 @@ bool of_FORCE(vthread_t thr, vvp_code_t cp)
|
|||
*/
|
||||
bool of_RELEASE(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
vvp_ipoint_t itgt = cp->iptr;
|
||||
functor_t tgt = functor_index(itgt);
|
||||
|
||||
if (release_force(itgt, tgt))
|
||||
tgt->enable(itgt);
|
||||
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement %%release\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -213,84 +219,14 @@ bool var_functor_s::deassign(vvp_ipoint_t itgt)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The %cassign instruction causes a variable functor (the target) the
|
||||
* receive a behavioral continuous assignment from the functor on the
|
||||
* right (the source expression). If the source functor address is 0,
|
||||
* then the port part is a constant value to write into the target.
|
||||
*/
|
||||
bool of_CASSIGN(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_ipoint_t itgt = cp->iptr;
|
||||
vvp_ipoint_t iexp = cp->iptr2;
|
||||
|
||||
functor_t tgt = functor_index(itgt);
|
||||
|
||||
var_functor_s *var = dynamic_cast<var_functor_s *>(tgt);
|
||||
assert(var);
|
||||
var->deassign(itgt);
|
||||
|
||||
// a constant expression?
|
||||
if (ipoint_make(iexp, 0) == 0) {
|
||||
tgt->port[3] = ipoint_make(0, 3);
|
||||
tgt->set(ipoint_make(itgt, 1), true, ipoint_port(iexp));
|
||||
return true;
|
||||
}
|
||||
|
||||
functor_t fu = functor_index(iexp);
|
||||
|
||||
tgt->port[3] = iexp;
|
||||
tgt->port[1] = fu->out;
|
||||
fu->out = ipoint_make(itgt, 1);
|
||||
|
||||
tgt->set(ipoint_make(itgt, 1), true, fu->get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_ipoint_t itgt = cp->iptr;
|
||||
unsigned wid = cp->bit_idx[0];
|
||||
|
||||
for (unsigned i = 0; i<wid; i++) {
|
||||
vvp_ipoint_t ipt = ipoint_index(itgt, i);
|
||||
functor_t tgt = functor_index(ipt);
|
||||
|
||||
var_functor_s *var = dynamic_cast<var_functor_s *>(tgt);
|
||||
assert(var);
|
||||
|
||||
var->deassign(ipt);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: force.cc,v $
|
||||
* Revision 1.9 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.8 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.7 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2002/08/07 00:54:20 steve
|
||||
* Documentation, and excessive inlines.
|
||||
*
|
||||
* Revision 1.5 2002/03/17 03:23:11 steve
|
||||
* Force the push flags to be explicit.
|
||||
*
|
||||
* Revision 1.4 2001/12/06 03:31:24 steve
|
||||
* Support functor delays for gates and UDP devices.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.3 2001/11/07 03:34:42 steve
|
||||
* Use functor pointers where vvp_ipoint_t is unneeded.
|
||||
*
|
||||
* Revision 1.2 2001/11/01 04:42:40 steve
|
||||
* Handle procedural constant functor pointers.
|
||||
*
|
||||
* Revision 1.1 2001/11/01 03:00:19 steve
|
||||
* Add force/cassign/release/deassign support. (Stephan Boettcher)
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.52 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.53 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "pointers.h"
|
||||
|
|
@ -277,15 +277,6 @@ unsigned functor_get(vvp_ipoint_t ptr)
|
|||
|
||||
// Special infrastructure functor types
|
||||
|
||||
/*
|
||||
* A "waitable" functor is one that the %wait instruction can wait
|
||||
* on. This includes the infrastructure needed to hold threads.
|
||||
*/
|
||||
struct waitable_hooks_s {
|
||||
vthread_t threads;
|
||||
};
|
||||
|
||||
|
||||
// The extra_outputs_functor_s class is for devices that require
|
||||
// multiple inputs and outputs.
|
||||
// ->set redirects the job to the base_, who knows what shall be done.
|
||||
|
|
@ -343,6 +334,11 @@ extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
|
|||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.53 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.52 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.43 2004/06/30 02:15:57 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.44 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -101,6 +101,7 @@
|
|||
".net" { return K_NET; }
|
||||
".net/s" { return K_NET_S; }
|
||||
".param" { return K_PARAM; }
|
||||
".part" { return K_PART; }
|
||||
".resolv" { return K_RESOLV; }
|
||||
".scope" { return K_SCOPE; }
|
||||
".shift/l" { return K_SHIFTL; }
|
||||
|
|
@ -182,6 +183,11 @@ int yywrap()
|
|||
|
||||
/*
|
||||
* $Log: lexor.lex,v $
|
||||
* Revision 1.44 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.43 2004/06/30 02:15:57 steve
|
||||
* Add signed LPM divide.
|
||||
*
|
||||
|
|
|
|||
115
vvp/logic.cc
115
vvp/logic.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: logic.cc,v 1.13 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: logic.cc,v 1.14 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "logic.h"
|
||||
|
|
@ -38,36 +38,14 @@
|
|||
* to 4 inputs.
|
||||
*/
|
||||
|
||||
table_functor_s::table_functor_s(truth_t t, unsigned str0, unsigned str1)
|
||||
table_functor_s::table_functor_s(truth_t t)
|
||||
: table(t)
|
||||
{
|
||||
count_functors_table += 1;
|
||||
assert(str0 <= 7);
|
||||
assert(str1 <= 7);
|
||||
odrive0 = str0;
|
||||
odrive1 = str1;
|
||||
}
|
||||
|
||||
table_functor_s::~table_functor_s()
|
||||
{}
|
||||
|
||||
void table_functor_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned)
|
||||
{
|
||||
/* Load the new value into the standard ival vector. */
|
||||
put(ptr, v);
|
||||
|
||||
/* Locate the new output value in the table. */
|
||||
unsigned char val = table[ival >> 2];
|
||||
val >>= 2 * (ival&0x03);
|
||||
val &= 0x03;
|
||||
|
||||
/* Send the output. Do *not* push the value, because logic
|
||||
devices in Verilog are supposed to suppress 0-time
|
||||
pulses. If we were to push the value, The gate on this
|
||||
device's output would receive every change that happened,
|
||||
thus allowing full transport propagation, instead of the
|
||||
proper ballistic propagation. */
|
||||
put_oval(val, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -80,26 +58,26 @@ void compile_functor(char*label, char*type,
|
|||
vvp_delay_t delay, unsigned ostr0, unsigned ostr1,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
functor_t obj;
|
||||
table_functor_s* obj = 0;
|
||||
|
||||
if (strcmp(type, "OR") == 0) {
|
||||
obj = new table_functor_s(ft_OR, ostr0, ostr1);
|
||||
obj = new table_functor_s(ft_OR);
|
||||
|
||||
} else if (strcmp(type, "AND") == 0) {
|
||||
obj = new table_functor_s(ft_AND, ostr0, ostr1);
|
||||
obj = new table_functor_s(ft_AND);
|
||||
|
||||
} else if (strcmp(type, "BUF") == 0) {
|
||||
obj = new table_functor_s(ft_BUF, ostr0, ostr1);
|
||||
|
||||
obj = new table_functor_s(ft_BUF);
|
||||
#if 0
|
||||
} else if (strcmp(type, "BUFIF0") == 0) {
|
||||
obj = new vvp_bufif_s(true,false, ostr0, ostr1);
|
||||
|
||||
} else if (strcmp(type, "BUFIF1") == 0) {
|
||||
obj = new vvp_bufif_s(false,false, ostr0, ostr1);
|
||||
|
||||
#endif
|
||||
} else if (strcmp(type, "BUFZ") == 0) {
|
||||
obj = new table_functor_s(ft_BUFZ, ostr0, ostr1);
|
||||
|
||||
obj = new table_functor_s(ft_BUFZ);
|
||||
#if 0
|
||||
} else if (strcmp(type, "PMOS") == 0) {
|
||||
obj = new vvp_pmos_s;
|
||||
|
||||
|
|
@ -111,7 +89,7 @@ void compile_functor(char*label, char*type,
|
|||
|
||||
} else if (strcmp(type, "RNMOS") == 0) {
|
||||
obj = new vvp_rnmos_s;
|
||||
|
||||
#endif
|
||||
} else if (strcmp(type, "MUXX") == 0) {
|
||||
obj = new table_functor_s(ft_MUXX);
|
||||
|
||||
|
|
@ -122,25 +100,25 @@ void compile_functor(char*label, char*type,
|
|||
obj = new table_functor_s(ft_EEQ);
|
||||
|
||||
} else if (strcmp(type, "NAND") == 0) {
|
||||
obj = new table_functor_s(ft_NAND, ostr0, ostr1);
|
||||
obj = new table_functor_s(ft_NAND);
|
||||
|
||||
} else if (strcmp(type, "NOR") == 0) {
|
||||
obj = new table_functor_s(ft_NOR, ostr0, ostr1);
|
||||
obj = new table_functor_s(ft_NOR);
|
||||
|
||||
} else if (strcmp(type, "NOT") == 0) {
|
||||
obj = new table_functor_s(ft_NOT, ostr0, ostr1);
|
||||
|
||||
obj = new table_functor_s(ft_NOT);
|
||||
#if 0
|
||||
} else if (strcmp(type, "NOTIF0") == 0) {
|
||||
obj = new vvp_bufif_s(true,true, ostr0, ostr1);
|
||||
|
||||
} else if (strcmp(type, "NOTIF1") == 0) {
|
||||
obj = new vvp_bufif_s(false,true, ostr0, ostr1);
|
||||
|
||||
#endif
|
||||
} else if (strcmp(type, "XNOR") == 0) {
|
||||
obj = new table_functor_s(ft_XNOR, ostr0, ostr1);
|
||||
obj = new table_functor_s(ft_XNOR);
|
||||
|
||||
} else if (strcmp(type, "XOR") == 0) {
|
||||
obj = new table_functor_s(ft_XOR, ostr0, ostr1);
|
||||
obj = new table_functor_s(ft_XOR);
|
||||
|
||||
} else {
|
||||
yyerror("invalid functor type.");
|
||||
|
|
@ -153,61 +131,22 @@ void compile_functor(char*label, char*type,
|
|||
free(type);
|
||||
|
||||
assert(argc <= 4);
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_define(fdx, obj);
|
||||
define_functor_symbol(label, fdx);
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
|
||||
define_functor_symbol(label, net);
|
||||
free(label);
|
||||
|
||||
obj->delay = delay;
|
||||
|
||||
inputs_connect(fdx, argc, argv);
|
||||
inputs_connect(net, argc, argv);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: logic.cc,v $
|
||||
* Revision 1.13 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.12 2002/09/06 04:56:29 steve
|
||||
* Add support for %v is the display system task.
|
||||
* Change the encoding of H and L outputs from
|
||||
* the bufif devices so that they are logic x.
|
||||
*
|
||||
* Revision 1.11 2002/08/29 03:04:01 steve
|
||||
* Generate x out for x select on wide muxes.
|
||||
*
|
||||
* Revision 1.10 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.9 2002/07/05 20:08:44 steve
|
||||
* Count different types of functors.
|
||||
*
|
||||
* Revision 1.8 2002/03/17 05:48:49 steve
|
||||
* Do not push values through logic gates.
|
||||
*
|
||||
* Revision 1.7 2002/01/12 04:02:16 steve
|
||||
* Support the BUFZ logic device.
|
||||
*
|
||||
* Revision 1.6 2001/12/14 06:03:17 steve
|
||||
* Arrange bufif to support notif as well.
|
||||
*
|
||||
* Revision 1.5 2001/12/14 02:04:49 steve
|
||||
* Support strength syntax on functors.
|
||||
*
|
||||
* Revision 1.4 2001/12/06 03:31:24 steve
|
||||
* Support functor delays for gates and UDP devices.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.3 2001/11/16 04:22:27 steve
|
||||
* include stdlib.h for portability.
|
||||
*
|
||||
* Revision 1.2 2001/11/07 03:34:42 steve
|
||||
* Use functor pointers where vvp_ipoint_t is unneeded.
|
||||
*
|
||||
* Revision 1.1 2001/11/06 03:07:22 steve
|
||||
* Code rearrange. (Stephan Boettcher)
|
||||
* Revision 1.14 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
40
vvp/logic.h
40
vvp/logic.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __logic_H
|
||||
#define __logic_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -19,25 +19,25 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: logic.h,v 1.7 2003/07/30 01:13:29 steve Exp $"
|
||||
#ident "$Id: logic.h,v 1.8 2004/12/11 02:31:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
# include "vvp_net.h"
|
||||
# include <stddef.h>
|
||||
|
||||
/*
|
||||
* Table driven functor. oval = table[ival];
|
||||
* Table driven functor. This kind of node takes 4 inputs and
|
||||
* generates a single output. The logic is bitwise, and implemented
|
||||
* with a lookup table.
|
||||
*/
|
||||
|
||||
class table_functor_s: public functor_s {
|
||||
class table_functor_s: public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
typedef const unsigned char *truth_t;
|
||||
explicit table_functor_s(truth_t t, unsigned str0 =6, unsigned str1 =6);
|
||||
explicit table_functor_s(truth_t t);
|
||||
virtual ~table_functor_s();
|
||||
|
||||
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
|
||||
private:
|
||||
truth_t table;
|
||||
};
|
||||
|
|
@ -66,26 +66,10 @@ extern const unsigned char ft_var[];
|
|||
|
||||
/*
|
||||
* $Log: logic.h,v $
|
||||
* Revision 1.7 2003/07/30 01:13:29 steve
|
||||
* Add support for triand and trior.
|
||||
*
|
||||
* Revision 1.6 2002/08/29 03:04:01 steve
|
||||
* Generate x out for x select on wide muxes.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2002/07/05 20:08:44 steve
|
||||
* Count different types of functors.
|
||||
*
|
||||
* Revision 1.3 2002/01/12 04:02:16 steve
|
||||
* Support the BUFZ logic device.
|
||||
*
|
||||
* Revision 1.2 2001/12/14 02:04:49 steve
|
||||
* Support strength syntax on functors.
|
||||
*
|
||||
* Revision 1.1 2001/11/06 03:07:22 steve
|
||||
* Code rearrange. (Stephan Boettcher)
|
||||
* Revision 1.8 2004/12/11 02:31:29 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
*/
|
||||
#endif // __logic_H
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: opcodes.txt,v 1.55 2004/06/19 15:52:53 steve Exp $
|
||||
* $Id: opcodes.txt,v 1.56 2004/12/11 02:31:29 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -57,9 +57,8 @@ means the following:
|
|||
1 and 1 --> 1
|
||||
otherwise x
|
||||
|
||||
* %assign <var-label>, <delay>, <bit>
|
||||
* %assign/d <var-label>, <delay>, <bit>
|
||||
* %assign/v0 <var-label>, <delay>, <bit>
|
||||
* %assign <var-label>, <delay>, <bit> (DEPRECATED -- use %assign/v0)
|
||||
* %assign/d <var-label>, <delay>, <bit> (DEPRECATED -- need %assign/v0/d)
|
||||
|
||||
This does a non-blocking assignment to a variable. The <label>
|
||||
identifies the affected variable, and the <delay> gives the delay when
|
||||
|
|
@ -71,9 +70,6 @@ The %assign/d instruction is exactly the same as the %assign
|
|||
instruction, except that the <delay> specifies one of the index
|
||||
registers, that contain a calculated delay.
|
||||
|
||||
The %assign/v0 instruction is a vector version of %assign, with the
|
||||
vector width in index register 0.
|
||||
|
||||
* %assign/m <memory-label>, <delay>, <bit>
|
||||
|
||||
This instruction does a non-blocking assignment to a bit in a memory
|
||||
|
|
@ -81,6 +77,16 @@ from the specified thread register <bit>. The memory bit is addressed
|
|||
by index register 3. Bit address zero is the LSB of the first memory
|
||||
word.
|
||||
|
||||
* %assign/v0 <var-label>, <delay>, <bit>
|
||||
|
||||
The %assign/v0 instruction is a vector version of non-blocking
|
||||
assignment. The <delay> is the number of clock ticks in the future
|
||||
where the assignment should be schedule, and the <bit> is the base of
|
||||
the vector to be assigned to the destination. The vector width is in
|
||||
index register 0.
|
||||
|
||||
The <var-label> references a .var object that can receive non-blocking
|
||||
assignments. For blocking assignments, see %set/v.
|
||||
|
||||
* %assign/wr <vpi-label>, <delay>, <index>
|
||||
|
||||
|
|
@ -124,20 +130,17 @@ debugger commands.
|
|||
This may not work on all platforms. If run-time debugging is compiled
|
||||
out, then this function is a no-op.
|
||||
|
||||
* %cassign/v <var-label>, <bit>, <wid>
|
||||
|
||||
* %cassign <var-label>, <expr-label>
|
||||
Perform a continuous assign of a constant value to the target
|
||||
variable. This is similar to %set, but it uses the cassign port
|
||||
(port-1) of the signal functor instead of the normal assign, so the
|
||||
signal responds differently.
|
||||
|
||||
Connect and active a procedural continuous assignment to a
|
||||
variable. The <var-label> identifies the affected variable, and the
|
||||
<expr-label> is the functor that drives the expression to the
|
||||
variable. This opcode affects only a single bit.
|
||||
|
||||
|
||||
* %deassign <var-label>, <wid>
|
||||
* %deassign <var-label>
|
||||
|
||||
Deactivate and disconnect a procedural continuous assignment to a
|
||||
variable. The <var-label> identifies the affected variable. <wid>
|
||||
specifies the how many bits to deassign.
|
||||
variable. The <var-label> identifies the affected variable.
|
||||
|
||||
|
||||
* %cmp/u <bit-l>, <bit-r>, <wid>
|
||||
|
|
@ -294,7 +297,7 @@ bits.
|
|||
This instruction loads an immediate value into the addressed index
|
||||
register. The index register holds numeric values, so the <value> is a
|
||||
number. The idx value selects the index register, and may be 0, 1, 2
|
||||
or 3. This is different from %is/get, which loads the index register
|
||||
or 3. This is different from %ix/get, which loads the index register
|
||||
from a value in the thread bit vector.
|
||||
|
||||
|
||||
|
|
@ -338,19 +341,6 @@ If the matching child instruction is still running, a %join suspends
|
|||
the calling thread until the child ends. If the child is already
|
||||
ended, then the %join does not block or yield the thread.
|
||||
|
||||
|
||||
* %load <bit>, <functor-label>
|
||||
* %load/v <bit>, <functor-label>, <wid>
|
||||
|
||||
This instruction loads a value from the given functor output into the
|
||||
specified thread register bit. The functor-label can refer to a .net,
|
||||
a .var or a .functor, and may be indexed with array syntax to get at a
|
||||
functor within a vector of functors. This instruction loads only a
|
||||
single bit.
|
||||
|
||||
The %load/v instruction is a vector version, that loads an entire
|
||||
vector, starting at the given <bit> and functor.
|
||||
|
||||
* %load/m <bit>, <memory-label>
|
||||
|
||||
This instruction loads a value from a memory bit into the specified
|
||||
|
|
@ -365,6 +355,15 @@ This instruction load a value from a .net object bit. Since .net
|
|||
objects don't really exist (they are only named indirection into the
|
||||
netlist) this instruction indexes into the .net list of bits.
|
||||
|
||||
* %load/v <bit>, <functor-label>, <wid>
|
||||
|
||||
This instruction loads a vector value from the given functor node into
|
||||
the specified thread register bit. The functor-label can refer to a
|
||||
.net, a .var or a .functor with a vector output. The entire vector,
|
||||
from the least significant up to <wid> bits, is loaded starting at
|
||||
thread bit <bit>. It is an error for the width to not match the vector
|
||||
width at the functor.
|
||||
|
||||
* %load/wr <bit>, <vpi-label>
|
||||
|
||||
This instruction reads a real value from the vpi-like object to a word
|
||||
|
|
@ -497,7 +496,6 @@ semantics. Like:
|
|||
%release <functor-label> ; remove the force
|
||||
|
||||
|
||||
* %set <var-label>, <bit>
|
||||
* %set/v <var-label>, <bit>, <wid>
|
||||
|
||||
This sets a bit of a variable, and is used to implement blocking
|
||||
|
|
|
|||
19
vvp/parse.y
19
vvp/parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.60 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.61 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -60,7 +60,7 @@ extern FILE*yyin;
|
|||
%token K_ARITH_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
|
||||
%token K_ARITH_SUB K_ARITH_SUM
|
||||
%token K_CMP_EQ K_CMP_NE K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
|
||||
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM
|
||||
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM K_PART
|
||||
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
%token K_MEM K_MEM_P K_MEM_I
|
||||
|
|
@ -181,6 +181,12 @@ statement
|
|||
compile_resolver($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
/* Part select statements take a single netlist input, and numbers
|
||||
that define the part to be selected out of the input. */
|
||||
|
||||
| T_LABEL K_PART T_SYMBOL ',' T_NUMBER ',' T_NUMBER ';'
|
||||
{ compile_part_select($1, $3, $5, $7); }
|
||||
|
||||
/* Force statements are very much like functors. They are
|
||||
compiled to functors of a different mode. */
|
||||
|
||||
|
|
@ -566,10 +572,6 @@ symbol
|
|||
{ $$.text = $1;
|
||||
$$.idx = 0;
|
||||
}
|
||||
| T_SYMBOL '[' T_NUMBER ']'
|
||||
{ $$.text = $1;
|
||||
$$.idx = $3;
|
||||
}
|
||||
;
|
||||
|
||||
symbol_opt
|
||||
|
|
@ -635,6 +637,11 @@ int compile_design(const char*path)
|
|||
|
||||
/*
|
||||
* $Log: parse.y,v $
|
||||
* Revision 1.61 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.60 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: resolv.cc,v 1.17 2003/03/13 04:36:57 steve Exp $"
|
||||
#ident "$Id: resolv.cc,v 1.18 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "resolv.h"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
# include "statistics.h"
|
||||
# include <assert.h>
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* A signal value is unambiguous if the top 4 bits and the bottom 4
|
||||
* bits are identical. This means that the VSSSvsss bits of the 8bit
|
||||
|
|
@ -187,31 +188,30 @@ void resolv_functor_s::set(vvp_ipoint_t i, bool push, unsigned, unsigned str)
|
|||
|
||||
put_ostr(val, sval, false);
|
||||
}
|
||||
#else
|
||||
|
||||
resolv_functor::resolv_functor(vvp_scaler_t hiz_value)
|
||||
: hiz_(hiz_value)
|
||||
{
|
||||
}
|
||||
|
||||
resolv_functor::~resolv_functor()
|
||||
{
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec8(vvp_vector8_t vit)
|
||||
{
|
||||
assert(0); // XXXX not implemented yet!
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: resolv.cc,v $
|
||||
* Revision 1.17 2003/03/13 04:36:57 steve
|
||||
* Remove the obsolete functor delete functions.
|
||||
* Revision 1.18 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.16 2003/02/09 23:33:26 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.15 2002/09/06 04:56:29 steve
|
||||
* Add support for %v is the display system task.
|
||||
* Change the encoding of H and L outputs from
|
||||
* the bufif devices so that they are logic x.
|
||||
*
|
||||
* Revision 1.14 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.13 2002/07/05 20:08:44 steve
|
||||
* Count different types of functors.
|
||||
*
|
||||
* Revision 1.12 2001/12/18 05:32:11 steve
|
||||
* Improved functor debug dumps.
|
||||
*
|
||||
* Revision 1.11 2001/12/15 02:11:51 steve
|
||||
* Give tri0 and tri1 their proper strengths.
|
||||
*/
|
||||
|
||||
|
|
|
|||
52
vvp/resolv.h
52
vvp/resolv.h
|
|
@ -19,59 +19,41 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: resolv.h,v 1.8 2003/03/13 04:36:57 steve Exp $"
|
||||
#ident "$Id: resolv.h,v 1.9 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "functor.h"
|
||||
# include "vvp_net.h"
|
||||
|
||||
/*
|
||||
* This functor type resolves its inputs using the verilog method of
|
||||
* combining signals, and outputs that resolved value. The puller
|
||||
* value is also blended with the result. This helps with the
|
||||
* implementation of tri0 and tri1, which have pull constants attached.
|
||||
* implementation of tri0 and tri1, which have pull constants
|
||||
* attached.
|
||||
*
|
||||
* This node takes in vvp_vector8_t values, and emits a vvp_vector8_t
|
||||
* value.
|
||||
*/
|
||||
class resolv_functor_s: public functor_s {
|
||||
class resolv_functor : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
explicit resolv_functor_s(unsigned char hiz_value);
|
||||
~resolv_functor_s();
|
||||
|
||||
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
explicit resolv_functor(vvp_scaler_t hiz_value);
|
||||
~resolv_functor();
|
||||
|
||||
void recv_vec8(vvp_vector8_t bit);
|
||||
|
||||
private:
|
||||
unsigned char istr[4];
|
||||
unsigned char hiz_;
|
||||
vvp_vector8_t driven_;
|
||||
vvp_scaler_t hiz_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: resolv.h,v $
|
||||
* Revision 1.8 2003/03/13 04:36:57 steve
|
||||
* Remove the obsolete functor delete functions.
|
||||
*
|
||||
* Revision 1.7 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2001/12/18 05:32:11 steve
|
||||
* Improved functor debug dumps.
|
||||
*
|
||||
* Revision 1.5 2001/12/15 02:11:51 steve
|
||||
* Give tri0 and tri1 their proper strengths.
|
||||
*
|
||||
* Revision 1.4 2001/12/15 01:54:39 steve
|
||||
* Support tri0 and tri1 resolvers.
|
||||
*
|
||||
* Revision 1.3 2001/10/31 04:27:47 steve
|
||||
* Rewrite the functor type to have fewer functor modes,
|
||||
* and use objects to manage the different types.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.2 2001/05/12 01:48:57 steve
|
||||
* Silly copyright typo.
|
||||
*
|
||||
* Revision 1.1 2001/05/09 02:53:53 steve
|
||||
* Implement the .resolv syntax.
|
||||
* Revision 1.9 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
146
vvp/schedule.cc
146
vvp/schedule.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: schedule.cc,v 1.28 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: schedule.cc,v 1.29 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "schedule.h"
|
||||
|
|
@ -43,30 +43,19 @@ unsigned long count_time_pool = 0;
|
|||
|
||||
/*
|
||||
* The event_s and event_time_s structures implement the Verilog
|
||||
* stratified event queue. The event_time_s objects are one per time
|
||||
* step. Each time step in turn contains a list of event_s objects
|
||||
* that are the actual events.
|
||||
* stratified event queue.
|
||||
*
|
||||
* The event_time_s objects are one per time step. Each time step in
|
||||
* turn contains a list of event_s objects that are the actual events.
|
||||
*
|
||||
* The event_s objects are base classes for the more specific sort of
|
||||
* event.
|
||||
*/
|
||||
struct event_s {
|
||||
|
||||
union {
|
||||
vthread_t thr;
|
||||
vvp_ipoint_t fun;
|
||||
functor_t funp;
|
||||
vvp_gen_event_t obj;
|
||||
};
|
||||
unsigned val :2;
|
||||
unsigned type :2;
|
||||
|
||||
struct event_s*next;
|
||||
|
||||
void* operator new (size_t);
|
||||
void operator delete(void*obj, size_t s);
|
||||
virtual ~event_s() { }
|
||||
virtual void run_run(void) =0;
|
||||
};
|
||||
const unsigned TYPE_GEN = 0;
|
||||
const unsigned TYPE_THREAD = 1;
|
||||
const unsigned TYPE_PROP = 2;
|
||||
const unsigned TYPE_ASSIGN = 3;
|
||||
|
||||
struct event_time_s {
|
||||
vvp_time64_t delay;
|
||||
|
|
@ -81,43 +70,50 @@ struct event_time_s {
|
|||
void operator delete(void*obj, size_t s);
|
||||
};
|
||||
|
||||
/*
|
||||
* Derived event types
|
||||
*/
|
||||
struct vthread_event_s : public event_s {
|
||||
vthread_t thr;
|
||||
void run_run(void);
|
||||
};
|
||||
|
||||
void vthread_event_s::run_run(void)
|
||||
{
|
||||
count_thread_events += 1;
|
||||
vthread_run(thr);
|
||||
}
|
||||
|
||||
struct assign_vector4_event_s : public event_s {
|
||||
vvp_net_ptr_t ptr;
|
||||
vvp_vector4_t val;
|
||||
void run_run(void);
|
||||
};
|
||||
|
||||
void assign_vector4_event_s::run_run(void)
|
||||
{
|
||||
count_assign_events += 1;
|
||||
vvp_send_vec4(ptr, val);
|
||||
}
|
||||
|
||||
struct generic_event_s : public event_s {
|
||||
vvp_gen_event_t obj;
|
||||
unsigned char val;
|
||||
void run_run(void);
|
||||
};
|
||||
|
||||
void generic_event_s::run_run(void)
|
||||
{
|
||||
count_gen_events += 1;
|
||||
if (obj && obj->run)
|
||||
obj->run(obj, val);
|
||||
}
|
||||
|
||||
/*
|
||||
** These event_s will be required a lot, at high frequency.
|
||||
** These event_time_s will be required a lot, at high frequency.
|
||||
** Once allocated, we never free them, but stash them away for next time.
|
||||
*/
|
||||
|
||||
static struct event_s* event_free_list = 0;
|
||||
static const unsigned CHUNK_COUNT = 8192 / sizeof(struct event_s);
|
||||
|
||||
inline void* event_s::operator new (size_t size)
|
||||
{
|
||||
assert(size == sizeof(struct event_s));
|
||||
|
||||
struct event_s* cur = event_free_list;
|
||||
if (!cur) {
|
||||
cur = (struct event_s*)
|
||||
malloc(CHUNK_COUNT * sizeof(struct event_s));
|
||||
for (unsigned idx = 1 ; idx < CHUNK_COUNT ; idx += 1) {
|
||||
cur[idx].next = event_free_list;
|
||||
event_free_list = cur + idx;
|
||||
}
|
||||
|
||||
count_event_pool += CHUNK_COUNT;
|
||||
|
||||
} else {
|
||||
event_free_list = cur->next;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
inline void event_s::operator delete(void*obj, size_t size)
|
||||
{
|
||||
struct event_s*cur = reinterpret_cast<event_s*>(obj);
|
||||
cur->next = event_free_list;
|
||||
event_free_list = cur;
|
||||
}
|
||||
|
||||
static struct event_time_s* time_free_list = 0;
|
||||
static const unsigned TIME_CHUNK_COUNT = 8192 / sizeof(struct event_time_s);
|
||||
|
|
@ -374,10 +370,9 @@ static struct event_s* pull_sync_event(void)
|
|||
|
||||
void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
|
||||
{
|
||||
struct event_s*cur = new event_s;
|
||||
struct vthread_event_s*cur = new vthread_event_s;
|
||||
|
||||
cur->thr = thr;
|
||||
cur->type = TYPE_THREAD;
|
||||
vthread_mark_scheduled(thr);
|
||||
|
||||
if (push_flag && (delay == 0)) {
|
||||
|
|
@ -394,14 +389,19 @@ void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
|
|||
|
||||
void functor_s::schedule(vvp_time64_t delay, bool nba_flag)
|
||||
{
|
||||
#if 0
|
||||
struct event_s*cur = new event_s;
|
||||
|
||||
cur->funp = this;
|
||||
cur->type = TYPE_PROP;
|
||||
|
||||
schedule_event_(cur, delay, nba_flag? SEQ_NBASSIGN:SEQ_ACTIVE);
|
||||
#else
|
||||
fprintf(stderr, "XXXX I forgot how to schedule functors.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
void schedule_assign(vvp_ipoint_t fun, unsigned char val, vvp_time64_t delay)
|
||||
{
|
||||
struct event_s*cur = new event_s;
|
||||
|
|
@ -412,15 +412,25 @@ void schedule_assign(vvp_ipoint_t fun, unsigned char val, vvp_time64_t delay)
|
|||
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
#endif
|
||||
|
||||
void schedule_assign_vector(vvp_net_ptr_t ptr,
|
||||
vvp_vector4_t bit,
|
||||
vvp_time64_t delay)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_generic(vvp_gen_event_t obj, unsigned char val,
|
||||
vvp_time64_t delay, bool sync_flag)
|
||||
{
|
||||
struct event_s*cur = new event_s;
|
||||
struct generic_event_s*cur = new generic_event_s;
|
||||
|
||||
cur->obj = obj;
|
||||
cur->val = val;
|
||||
cur->type= TYPE_GEN;
|
||||
|
||||
schedule_event_(cur, delay, sync_flag? SEQ_ROSYNC : SEQ_ACTIVE);
|
||||
}
|
||||
|
|
@ -459,10 +469,7 @@ void schedule_simulate(void)
|
|||
|
||||
struct event_s*sync_cur;
|
||||
while ( (sync_cur = pull_sync_event()) ) {
|
||||
assert(sync_cur->type == TYPE_GEN);
|
||||
if (sync_cur->obj && sync_cur->obj->run) {
|
||||
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
|
||||
}
|
||||
sync_cur->run_run();
|
||||
delete sync_cur;
|
||||
}
|
||||
|
||||
|
|
@ -499,6 +506,8 @@ void schedule_simulate(void)
|
|||
ctim->active->next = cur->next;
|
||||
}
|
||||
|
||||
cur->run_run();
|
||||
#if 0
|
||||
switch (cur->type) {
|
||||
case TYPE_THREAD:
|
||||
count_thread_events += 1;
|
||||
|
|
@ -529,7 +538,7 @@ void schedule_simulate(void)
|
|||
break;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
delete (cur);
|
||||
}
|
||||
|
||||
|
|
@ -539,10 +548,7 @@ void schedule_simulate(void)
|
|||
for (struct event_s*sync_cur = pull_sync_event()
|
||||
; sync_cur ; sync_cur = pull_sync_event()) {
|
||||
|
||||
assert(sync_cur->type == TYPE_GEN);
|
||||
|
||||
if (sync_cur->obj && sync_cur->obj->run)
|
||||
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
|
||||
sync_cur->run_run();
|
||||
|
||||
delete (sync_cur);
|
||||
}
|
||||
|
|
@ -556,6 +562,11 @@ void schedule_simulate(void)
|
|||
|
||||
/*
|
||||
* $Log: schedule.cc,v $
|
||||
* Revision 1.29 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.28 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
@ -570,8 +581,5 @@ void schedule_simulate(void)
|
|||
*
|
||||
* Revision 1.24 2003/02/22 02:52:06 steve
|
||||
* Check for stopped flag in certain strategic points.
|
||||
*
|
||||
* Revision 1.23 2003/02/21 03:40:35 steve
|
||||
* Add vpiStop and interactive mode.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: schedule.h,v 1.16 2003/09/09 00:56:45 steve Exp $"
|
||||
#ident "$Id: schedule.h,v 1.17 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
# include "pointers.h"
|
||||
# include "vvp_net.h"
|
||||
|
||||
/*
|
||||
* This causes a thread to be scheduled for execution. The schedule
|
||||
|
|
@ -41,8 +42,9 @@ extern void schedule_vthread(vthread_t thr, vvp_time64_t delay,
|
|||
* Create an assignment event. The val passed here will be assigned to
|
||||
* the specified input when the delay times out.
|
||||
*/
|
||||
extern void schedule_assign(vvp_ipoint_t fun, unsigned char val,
|
||||
vvp_time64_t delay);
|
||||
extern void schedule_assign_vector(vvp_net_ptr_t ptr,
|
||||
vvp_vector4_t val,
|
||||
vvp_time64_t delay);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -108,28 +110,15 @@ extern unsigned long count_event_pool;
|
|||
|
||||
/*
|
||||
* $Log: schedule.h,v $
|
||||
* Revision 1.17 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.16 2003/09/09 00:56:45 steve
|
||||
* Reimpelement scheduler to divide nonblocking assign queue out.
|
||||
*
|
||||
* Revision 1.15 2003/02/22 02:52:06 steve
|
||||
* Check for stopped flag in certain strategic points.
|
||||
*
|
||||
* Revision 1.14 2003/02/21 03:40:35 steve
|
||||
* Add vpiStop and interactive mode.
|
||||
*
|
||||
* Revision 1.13 2003/02/09 23:33:26 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.12 2003/01/06 23:57:26 steve
|
||||
* Schedule wait lists of threads as a single event,
|
||||
* to save on events. Also, improve efficiency of
|
||||
* event_s allocation. Add some event statistics to
|
||||
* get an idea where performance is really going.
|
||||
*
|
||||
* Revision 1.11 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.10 2002/05/12 23:44:41 steve
|
||||
* task calls and forks push the thread event in the queue.
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: symbols.h,v 1.4 2002/08/12 01:35:08 steve Exp $"
|
||||
#ident "$Id: symbols.h,v 1.5 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
|
||||
/*
|
||||
* This is the basic type of a symbol table. It is opaque. Don't even
|
||||
|
|
@ -49,8 +50,9 @@ typedef struct symbol_table_s *symbol_table_t;
|
|||
|
||||
typedef struct symbol_value_s {
|
||||
union {
|
||||
unsigned long num;
|
||||
vvp_net_t*net;
|
||||
void*ptr;
|
||||
unsigned long num;
|
||||
};
|
||||
} symbol_value_t;
|
||||
|
||||
|
|
@ -79,6 +81,11 @@ symbol_value_t sym_get_value(symbol_table_t tbl, const char*key);
|
|||
|
||||
/*
|
||||
* $Log: symbols.h,v $
|
||||
* Revision 1.5 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
|
|
|||
12
vvp/ufunc.cc
12
vvp/ufunc.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ufunc.cc,v 1.4 2003/07/03 20:03:36 steve Exp $"
|
||||
#ident "$Id: ufunc.cc,v 1.5 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
|
|
@ -138,7 +138,7 @@ void compile_ufunc(char*label, char*code, unsigned wid,
|
|||
unsigned portc, struct symb_s*portv,
|
||||
unsigned retc, struct symb_s*retv)
|
||||
{
|
||||
|
||||
#if 0
|
||||
/* Create an array of vvp_ipoint_t pointers, that point to the
|
||||
.var bits of the function ports. Do this for the input
|
||||
ports and the output port. */
|
||||
|
|
@ -232,10 +232,18 @@ void compile_ufunc(char*label, char*code, unsigned wid,
|
|||
}
|
||||
|
||||
inputs_connect(ibase, argc, argv);
|
||||
#else
|
||||
fprintf(stderr, "XXXX compile_ufunc not implemented.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: ufunc.cc,v $
|
||||
* Revision 1.5 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.4 2003/07/03 20:03:36 steve
|
||||
* Remove the vvp_cpoint_t indirect code pointer.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_callback.cc,v 1.34 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: vpi_callback.cc,v 1.35 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -96,85 +96,6 @@ struct __vpiCallback* new_vpi_callback()
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* The callback_functor_s functor is used to support cbValueChange
|
||||
* callbacks. When a value change callback is created, instances of
|
||||
* this functor are created to receive values and detect changes in
|
||||
* the functor web at the right spot.
|
||||
*/
|
||||
|
||||
struct callback_functor_s: public functor_s {
|
||||
callback_functor_s();
|
||||
virtual ~callback_functor_s();
|
||||
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
struct __vpiCallback *cb_handle;
|
||||
};
|
||||
|
||||
callback_functor_s::callback_functor_s()
|
||||
{}
|
||||
|
||||
callback_functor_s::~callback_functor_s()
|
||||
{}
|
||||
|
||||
/*
|
||||
* Make the functors necessary to support an edge callback. This is a
|
||||
* single event functor that is in turn fed by edge detector functors
|
||||
* attached to all the input bit functors. (Just like an event-or.)
|
||||
* This function creates the callback_functor and the necessary event
|
||||
* functors, and attaches the event functors to the net.
|
||||
*/
|
||||
struct callback_functor_s *vvp_fvector_make_callback(vvp_fvector_t vec,
|
||||
event_functor_s::edge_t edge)
|
||||
{
|
||||
// Let's make a callback functor.
|
||||
struct callback_functor_s *obj = new callback_functor_s;
|
||||
|
||||
// We want to connect nvec inputs
|
||||
unsigned nvec = vvp_fvector_size(vec);
|
||||
|
||||
// We require a total of nfun functors. If there's an edge to
|
||||
// look for, then all inputs must go to extra event functors.
|
||||
// Otherwise we just make sure we have one input left on the base
|
||||
// functor to connect the extras to, if there are any.
|
||||
unsigned nfun = (nvec+3)/4;
|
||||
if (edge != vvp_edge_none)
|
||||
nfun ++ ;
|
||||
else if (nfun > 1 && 4*nfun == nvec)
|
||||
nfun ++;
|
||||
|
||||
vvp_ipoint_t fdx = functor_allocate(nfun);
|
||||
functor_define(fdx, obj);
|
||||
|
||||
for (unsigned i=1; i<nfun; i++) {
|
||||
functor_t fu = new event_functor_s(edge);
|
||||
functor_define(ipoint_index(fdx, i), fu);
|
||||
fu->out = fdx;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
|
||||
if (edge != vvp_edge_none)
|
||||
i = 4;
|
||||
else if (nvec > 4)
|
||||
i = 1;
|
||||
else
|
||||
i = 0;
|
||||
|
||||
for (unsigned vi = 0; vi < nvec; vi++, i++) {
|
||||
vvp_ipoint_t vipt = vvp_fvector_get(vec, vi);
|
||||
functor_t vfu = functor_index(vipt);
|
||||
|
||||
vvp_ipoint_t ipt = ipoint_input_index(fdx, i);
|
||||
functor_t fu = functor_index(ipt);
|
||||
unsigned pp = ipoint_port(ipt);
|
||||
|
||||
fu->port[pp] = vfu->out;
|
||||
vfu->out = ipt;
|
||||
}
|
||||
|
||||
obj->cb_handle = 0;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* A value change callback is tripped when a bit of a signal
|
||||
|
|
@ -202,21 +123,18 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
|
|||
case vpiReg:
|
||||
case vpiNet:
|
||||
case vpiIntegerVar:
|
||||
/* Attach the callback to the vvp_fun_signal node by
|
||||
putting it in the vpi_callbacks list. */
|
||||
struct __vpiSignal*sig;
|
||||
sig = reinterpret_cast<__vpiSignal*>(data->obj);
|
||||
|
||||
/* Create callback functors, if necessary, to do the
|
||||
value change detection and carry the callback
|
||||
objects. */
|
||||
if (sig->callback == 0) {
|
||||
sig->callback = vvp_fvector_make_callback(sig->bits);
|
||||
assert(sig->callback);
|
||||
}
|
||||
vvp_fun_signal*sig_fun;
|
||||
sig_fun = dynamic_cast<vvp_fun_signal*>(sig->node->fun);
|
||||
assert(sig_fun);
|
||||
|
||||
/* Attach the __vpiCallback object to the signals
|
||||
callback functors. */
|
||||
obj->next = sig->callback->cb_handle;
|
||||
sig->callback->cb_handle = obj;
|
||||
/* Attach the __vpiCallback object to the signal. */
|
||||
obj->next = sig_fun->vpi_callbacks;
|
||||
sig_fun->vpi_callbacks = obj;
|
||||
break;
|
||||
|
||||
case vpiRealVar:
|
||||
|
|
@ -512,25 +430,25 @@ void callback_execute(struct __vpiCallback*cur)
|
|||
}
|
||||
|
||||
/*
|
||||
* A callback_functor_s functor uses its set method to detect value
|
||||
* changes. When a value comes in, the __vpiCallback objects that are
|
||||
* associated with this callback functor are all called.
|
||||
* A vvp_fun_signal uses this method to run its callbacks whenever it
|
||||
* has a value change. If the cb_rtn is non-nil, then call the
|
||||
* callback function. If the cb_rtn pointer is nil, then the object
|
||||
* has been marked for deletion. Free it.
|
||||
*/
|
||||
|
||||
void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
|
||||
void vvp_fun_signal::run_vpi_callbacks()
|
||||
{
|
||||
struct __vpiCallback *next = cb_handle;
|
||||
struct __vpiCallback *next = vpi_callbacks;
|
||||
struct __vpiCallback *prev = 0;
|
||||
|
||||
while (next) {
|
||||
struct __vpiCallback * cur = next;
|
||||
struct __vpiCallback*cur = next;
|
||||
next = cur->next;
|
||||
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
if (cur->cb_data.value) {
|
||||
switch (cur->cb_data.value->format) {
|
||||
case vpiScalarVal:
|
||||
cur->cb_data.value->value.scalar = val;
|
||||
cur->cb_data.value->value.scalar = value(0);
|
||||
break;
|
||||
case vpiSuppressVal:
|
||||
break;
|
||||
|
|
@ -546,7 +464,7 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
|
|||
|
||||
} else if (prev == 0) {
|
||||
|
||||
cb_handle = next;
|
||||
vpi_callbacks = next;
|
||||
cur->next = 0;
|
||||
vpi_free_object(&cur->base);
|
||||
|
||||
|
|
@ -556,89 +474,21 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
|
|||
cur->next = 0;
|
||||
vpi_free_object(&cur->base);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* $Log: vpi_callback.cc,v $
|
||||
* Revision 1.35 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.34 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.33 2004/02/18 02:51:59 steve
|
||||
* Fix type mismatches of various VPI functions.
|
||||
*
|
||||
* Revision 1.32 2003/09/09 00:56:45 steve
|
||||
* Reimpelement scheduler to divide nonblocking assign queue out.
|
||||
*
|
||||
* Revision 1.31 2003/04/25 04:36:42 steve
|
||||
* Properly skip cancelled callbacks.
|
||||
*
|
||||
* Revision 1.30 2003/04/19 23:32:57 steve
|
||||
* Add support for cbNextSimTime.
|
||||
*
|
||||
* Revision 1.29 2003/03/12 02:50:32 steve
|
||||
* Add VPI tracing.
|
||||
*
|
||||
* Revision 1.28 2003/02/17 00:58:38 steve
|
||||
* Strict correctness of vpi_free_object results.
|
||||
*
|
||||
* Revision 1.27 2003/02/10 05:20:10 steve
|
||||
* Add value change callbacks to real variables.
|
||||
*
|
||||
* Revision 1.26 2003/02/09 23:33:26 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.25 2002/09/20 02:42:11 steve
|
||||
* Add support for cbAfterDelay.
|
||||
*
|
||||
* Revision 1.24 2002/09/07 04:54:51 steve
|
||||
* Implement vpi_remove_cb for cbValueChange.
|
||||
*
|
||||
* Revision 1.23 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.22 2002/07/31 03:22:23 steve
|
||||
* Set vpi_mode_flag to represent cpReadOnlySync actions.
|
||||
*
|
||||
* Revision 1.21 2002/07/12 02:07:36 steve
|
||||
* vpiIntegerVars can have callbacks.
|
||||
*
|
||||
* Revision 1.20 2002/06/11 03:47:34 steve
|
||||
* Stub value change callbacks for consts and modules.
|
||||
*
|
||||
* Revision 1.19 2002/06/02 19:05:50 steve
|
||||
* Check for null pointers from users.
|
||||
*
|
||||
* Revision 1.18 2002/05/28 22:55:20 steve
|
||||
* Callbacks can happen during calltf functions.
|
||||
*
|
||||
* Revision 1.17 2002/05/19 05:18:16 steve
|
||||
* Add callbacks for vpiNamedEvent objects.
|
||||
*
|
||||
* Revision 1.16 2002/05/18 02:34:11 steve
|
||||
* Add vpi support for named events.
|
||||
*
|
||||
* Add vpi_mode_flag to track the mode of the
|
||||
* vpi engine. This is for error checking.
|
||||
*
|
||||
* Revision 1.15 2002/05/09 03:34:31 steve
|
||||
* Handle null time and calltf pointers.
|
||||
*
|
||||
* Revision 1.14 2002/05/04 03:17:29 steve
|
||||
* Properly free vpi callback objects.
|
||||
*
|
||||
* Revision 1.13 2002/05/04 03:03:17 steve
|
||||
* Add simulator event callbacks.
|
||||
*
|
||||
* Revision 1.12 2002/04/20 04:33:23 steve
|
||||
* Support specified times in cbReadOnlySync, and
|
||||
* add support for cbReadWriteSync.
|
||||
* Keep simulation time in a 64bit number.
|
||||
*
|
||||
* Revision 1.11 2002/04/06 20:25:45 steve
|
||||
* cbValueChange automatically replays.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_event.cc,v 1.9 2003/05/04 20:43:36 steve Exp $"
|
||||
#ident "$Id: vpi_event.cc,v 1.10 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -86,7 +86,7 @@ static const struct __vpirt vpip_named_event_rt = {
|
|||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_named_event(const char*name, vvp_ipoint_t funct)
|
||||
vpiHandle vpip_make_named_event(const char*name, vvp_net_t*funct)
|
||||
{
|
||||
struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)
|
||||
malloc(sizeof(struct __vpiNamedEvent));
|
||||
|
|
@ -142,6 +142,11 @@ void vpip_run_named_event_callbacks(vpiHandle ref)
|
|||
|
||||
/*
|
||||
* $Log: vpi_event.cc,v $
|
||||
* Revision 1.10 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.9 2003/05/04 20:43:36 steve
|
||||
* Event callbacks support vpi_remove_cb.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_priv.h,v 1.59 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.60 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include "pointers.h"
|
||||
# include "vvp_net.h"
|
||||
# include "memory.h"
|
||||
|
||||
/*
|
||||
|
|
@ -177,16 +178,14 @@ struct __vpiSignal {
|
|||
unsigned signed_flag : 1;
|
||||
unsigned isint_ : 1; // original type was integer
|
||||
/* The represented value is here. */
|
||||
vvp_fvector_t bits;
|
||||
/* This is the callback event functor */
|
||||
struct callback_functor_s *callback;
|
||||
vvp_net_t*node;
|
||||
};
|
||||
extern vpiHandle vpip_make_int(const char*name, int msb, int lsb,
|
||||
vvp_fvector_t vec);
|
||||
vvp_net_t*vec);
|
||||
extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_fvector_t vec);
|
||||
bool signed_flag, vvp_net_t*net);
|
||||
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_fvector_t vec);
|
||||
bool signed_flag, vvp_net_t*node);
|
||||
|
||||
/*
|
||||
* These methods support the vpi creation of events. The name string
|
||||
|
|
@ -200,12 +199,12 @@ struct __vpiNamedEvent {
|
|||
/* Parent scope of this object. */
|
||||
struct __vpiScope*scope;
|
||||
/* The functor, used for %set operations. */
|
||||
vvp_ipoint_t funct;
|
||||
vvp_net_t*funct;
|
||||
/* List of callbacks interested in this event. */
|
||||
struct __vpiCallback*callbacks;
|
||||
};
|
||||
|
||||
extern vpiHandle vpip_make_named_event(const char*name, vvp_ipoint_t f);
|
||||
extern vpiHandle vpip_make_named_event(const char*name, vvp_net_t*f);
|
||||
extern void vpip_run_named_event_callbacks(vpiHandle ref);
|
||||
extern void vpip_real_value_change(struct __vpiCallback*cbh,
|
||||
vpiHandle ref);
|
||||
|
|
@ -418,6 +417,11 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
|
|||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.60 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.59 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_signal.cc,v 1.62 2004/05/19 03:26:25 steve Exp $"
|
||||
#ident "$Id: vpi_signal.cc,v 1.63 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -107,7 +107,7 @@ static int signal_get(int code, vpiHandle ref)
|
|||
|
||||
case _vpiNexusId:
|
||||
if (rfp->msb == rfp->lsb)
|
||||
return vvp_fvector_get(rfp->bits, 0);
|
||||
return (int)rfp->node;
|
||||
else
|
||||
return 0;
|
||||
|
||||
|
|
@ -178,10 +178,12 @@ static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
|
|||
? (rfp->msb - rfp->lsb + 1)
|
||||
: (rfp->lsb - rfp->msb + 1);
|
||||
|
||||
unsigned char*bits = new unsigned char[wid];
|
||||
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
|
||||
/* FIXME: bits should be an array of vvp_bit4_t. */
|
||||
unsigned char* bits = new unsigned char[wid];
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
bits[idx] = functor_get(fptr);
|
||||
bits[idx] = vsig->value(idx);
|
||||
}
|
||||
|
||||
unsigned hwid = (wid+2) / 3 + 1;
|
||||
|
|
@ -201,6 +203,7 @@ static char *signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
|
|||
? (rfp->msb - rfp->lsb + 1)
|
||||
: (rfp->lsb - rfp->msb + 1);
|
||||
|
||||
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
|
||||
|
||||
/* The result will use a character for each 8 bits of the
|
||||
vector. Add one extra character for the highest bits that
|
||||
|
|
@ -211,13 +214,12 @@ static char *signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
|
|||
char tmp = 0;
|
||||
int bitnr;
|
||||
for(bitnr=wid-1; bitnr>=0; bitnr--){
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, bitnr);
|
||||
tmp <<= 1;
|
||||
|
||||
switch (functor_get(fptr)) {
|
||||
case 0:
|
||||
switch (vsig->value(bitnr)) {
|
||||
case BIT4_0:
|
||||
break;
|
||||
case 1:
|
||||
case BIT4_1:
|
||||
tmp |= 1;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -254,6 +256,9 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
unsigned wid = (rfp->msb >= rfp->lsb)
|
||||
? (rfp->msb - rfp->lsb + 1)
|
||||
: (rfp->lsb - rfp->msb + 1);
|
||||
|
||||
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
|
||||
|
||||
char *rbuf = 0;
|
||||
|
||||
switch (vp->format) {
|
||||
|
|
@ -262,11 +267,10 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
assert(wid <= 8 * sizeof vp->value.integer);
|
||||
vp->value.integer = 0;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
switch (functor_get(fptr)) {
|
||||
case 0:
|
||||
switch (vsig->value(idx)) {
|
||||
case BIT4_0:
|
||||
break;
|
||||
case 1:
|
||||
case BIT4_1:
|
||||
vp->value.integer |= 1<<idx;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -278,18 +282,17 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
break;
|
||||
|
||||
case vpiScalarVal: {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, 0);
|
||||
switch (functor_get(fptr)) {
|
||||
case 0:
|
||||
switch (vsig->value(0)) {
|
||||
case BIT4_0:
|
||||
vp->value.scalar = vpi0;
|
||||
break;
|
||||
case 1:
|
||||
case BIT4_1:
|
||||
vp->value.scalar = vpi1;
|
||||
break;
|
||||
case 2:
|
||||
case BIT4_X:
|
||||
vp->value.scalar = vpiX;
|
||||
break;
|
||||
case 3:
|
||||
case BIT4_Z:
|
||||
vp->value.scalar = vpiZ;
|
||||
break;
|
||||
}
|
||||
|
|
@ -301,8 +304,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
rbuf = need_result_buf(wid+1, RBUF_VAL);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
rbuf[wid-idx-1] = "01xz"[functor_get(fptr)];
|
||||
rbuf[wid-idx-1] = "01xz"[vsig->value(idx)];
|
||||
}
|
||||
rbuf[wid] = 0;
|
||||
vp->value.str = rbuf;
|
||||
|
|
@ -316,8 +318,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
rbuf[hwid] = 0;
|
||||
hval = 0;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
hval = hval | (functor_get(fptr) << 2*(idx % 4));
|
||||
hval = hval | (vsig->value(idx) << 2*(idx % 4));
|
||||
|
||||
if (idx%4 == 3) {
|
||||
hwid -= 1;
|
||||
|
|
@ -353,8 +354,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
rbuf[hwid] = 0;
|
||||
hval = 0;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
hval = hval | (functor_get(fptr) << 2*(idx % 3));
|
||||
hval = hval | (vsig->value(idx) << 2*(idx % 3));
|
||||
|
||||
if (idx%3 == 2) {
|
||||
hwid -= 1;
|
||||
|
|
@ -400,21 +400,20 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
|
||||
op->aval = op->bval = 0;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
switch (functor_get(fptr)) {
|
||||
case 0:
|
||||
switch (vsig->value(idx)) {
|
||||
case BIT4_0:
|
||||
op->aval &= ~(1 << obit);
|
||||
op->bval &= ~(1 << obit);
|
||||
break;
|
||||
case 1:
|
||||
case BIT4_1:
|
||||
op->aval |= (1 << obit);
|
||||
op->bval &= ~(1 << obit);
|
||||
break;
|
||||
case 2:
|
||||
case BIT4_X:
|
||||
op->aval |= (1 << obit);
|
||||
op->bval |= (1 << obit);
|
||||
break;
|
||||
case 3:
|
||||
case BIT4_Z:
|
||||
op->aval &= ~(1 << obit);
|
||||
op->bval |= (1 << obit);
|
||||
break;
|
||||
|
|
@ -430,51 +429,6 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
break;
|
||||
}
|
||||
|
||||
case vpiStrengthVal: {
|
||||
s_vpi_strengthval*op = (s_vpi_strengthval*)
|
||||
need_result_buf(wid * sizeof(s_vpi_strengthval),
|
||||
RBUF_VAL);
|
||||
vp->value.strength = op;
|
||||
|
||||
/* Convert the internal strength values of each
|
||||
functor in the vector to a PLI2.0 version. */
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
||||
functor_t fp = functor_index(fptr);
|
||||
|
||||
unsigned str = fp->get_ostr();
|
||||
unsigned s0 = 1 << (str&0x07);
|
||||
unsigned s1 = 1 << ((str>>4) & 0x07);
|
||||
|
||||
switch (fp->get()) {
|
||||
case 0:
|
||||
op[idx].logic = vpi0;
|
||||
op[idx].s0 = s0|s1;
|
||||
op[idx].s1 = 0;
|
||||
break;
|
||||
case 1:
|
||||
op[idx].logic = vpi1;
|
||||
op[idx].s0 = 0;
|
||||
op[idx].s1 = s0|s1;
|
||||
break;
|
||||
case 2:
|
||||
op[idx].logic = vpiX;
|
||||
op[idx].s0 = s0;
|
||||
op[idx].s1 = s1;
|
||||
break;
|
||||
case 3:
|
||||
op[idx].logic = vpiZ;
|
||||
op[idx].s0 = vpiHiZ;
|
||||
op[idx].s1 = vpiHiZ;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp internal error: get_value: "
|
||||
"value type %u not implemented."
|
||||
|
|
@ -494,14 +448,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
|
||||
unsigned val, unsigned str, unsigned long dly =0)
|
||||
{
|
||||
vvp_ipoint_t ptr = vvp_fvector_get(rfp->bits,idx);
|
||||
|
||||
if (dly > 0) {
|
||||
schedule_assign(ptr, val, dly);
|
||||
} else {
|
||||
functor_t fu = functor_index(ptr);
|
||||
fu->put_ostr(val, str, true);
|
||||
}
|
||||
fprintf(stderr, "XXXX functor_poke not implemented\n");
|
||||
}
|
||||
|
||||
static void signal_put_stringval(struct __vpiSignal*rfp, unsigned wid,
|
||||
|
|
@ -762,7 +709,7 @@ static const struct __vpirt vpip_net_rt = {
|
|||
* to minimize the code modifications. Icarus implements integers
|
||||
* as 'reg signed [31:0]'.
|
||||
*/
|
||||
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_fvector_t vec)
|
||||
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, true, vec);
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
|
|
@ -775,7 +722,7 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_fvector_t vec)
|
|||
* Construct a vpiReg object. It's like a net, except for the type.
|
||||
*/
|
||||
vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_fvector_t vec)
|
||||
bool signed_flag, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
|
|
@ -804,7 +751,7 @@ static struct __vpiSignal* allocate_vpiSignal(void)
|
|||
* and point to the specified functor for the lsb.
|
||||
*/
|
||||
vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_fvector_t vec)
|
||||
bool signed_flag, vvp_net_t*node)
|
||||
{
|
||||
struct __vpiSignal*obj = allocate_vpiSignal();
|
||||
obj->base.vpi_type = &vpip_net_rt;
|
||||
|
|
@ -813,8 +760,7 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
obj->lsb = lsb;
|
||||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
obj->isint_ = false;
|
||||
obj->bits = vec;
|
||||
obj->callback = 0;
|
||||
obj->node = node;
|
||||
|
||||
obj->scope = vpip_peek_current_scope();
|
||||
|
||||
|
|
@ -826,6 +772,11 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
|
||||
/*
|
||||
* $Log: vpi_signal.cc,v $
|
||||
* Revision 1.63 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.62 2004/05/19 03:26:25 steve
|
||||
* Support delayed/non-blocking assignment to reals and others.
|
||||
*
|
||||
|
|
|
|||
226
vvp/vthread.cc
226
vvp/vthread.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vthread.cc,v 1.122 2004/10/04 01:11:00 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.123 2004/12/11 02:31:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -138,12 +138,12 @@ static void thr_check_addr(struct vthread_s*thr, unsigned addr)
|
|||
}
|
||||
}
|
||||
|
||||
static inline unsigned thr_get_bit(struct vthread_s*thr, unsigned addr)
|
||||
static inline vvp_bit4_t thr_get_bit(struct vthread_s*thr, unsigned addr)
|
||||
{
|
||||
assert(addr < thr->nbits);
|
||||
unsigned idx = addr % (CPU_WORD_BITS/2);
|
||||
addr /= (CPU_WORD_BITS/2);
|
||||
return (thr->bits[addr] >> (idx*2)) & 3UL;
|
||||
return (vvp_bit4_t) ((thr->bits[addr] >> (idx*2)) & 3UL);
|
||||
}
|
||||
|
||||
static inline void thr_put_bit(struct vthread_s*thr,
|
||||
|
|
@ -218,6 +218,31 @@ static unsigned long* vector_to_array(struct vthread_s*thr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets from the thread a vector of bits starting from
|
||||
* the addressed location and for the specified width.
|
||||
*/
|
||||
static vvp_vector4_t vthread_bits_to_vector(struct vthread_s*thr,
|
||||
unsigned bit, unsigned wid)
|
||||
{
|
||||
/* Make a vector of the desired width. */
|
||||
vvp_vector4_t value (wid);
|
||||
|
||||
if (bit >= 4) {
|
||||
for (unsigned idx = 0; idx < wid; idx +=1, bit += 1) {
|
||||
vvp_bit4_t bit_val = thr_get_bit(thr, bit);
|
||||
value.set_bit(idx, bit_val);
|
||||
}
|
||||
} else {
|
||||
vvp_bit4_t bit_val = (vvp_bit4_t)bit;
|
||||
for (unsigned idx = 0; idx < wid; idx +=1, bit += 1) {
|
||||
value.set_bit(idx, bit_val);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a new thread with the given start address.
|
||||
|
|
@ -517,18 +542,15 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool of_ASSIGN(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
|
||||
schedule_assign(cp->iptr, bit_val, cp->bit_idx[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_ASSIGN_D(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
assert(cp->bit_idx[0] < 4);
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
|
||||
schedule_assign(cp->iptr, bit_val, thr->words[cp->bit_idx[0]].w_int);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implemented %%assign/d\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -544,15 +566,10 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
|
|||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
unsigned char bit_val = thr_get_bit(thr, bit);
|
||||
schedule_assign(iptr, bit_val, delay);
|
||||
|
||||
if (bit >= 4)
|
||||
bit += 1;
|
||||
}
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
schedule_assign_vector(ptr, value, delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -584,9 +601,13 @@ bool of_ASSIGN_WR(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
|
||||
vvp_ipoint_t itmp = ipoint_index(cp->iptr, thr->words[0].w_int);
|
||||
schedule_assign(itmp, bit_val, cp->bit_idx[0]);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement %%assign/x0\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -624,6 +645,34 @@ bool of_BREAKPOINT(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* the %cassign/v instruction invokes a continuous assign of a
|
||||
* constant value to a signal. The instruction arguments are:
|
||||
*
|
||||
* %cassign/v <net>, <base>, <wid> ;
|
||||
*
|
||||
* Where the <net> is the net label assembled into a vvp_net pointer,
|
||||
* and the <base> and <wid> are stashed in the bit_idx array.
|
||||
*
|
||||
* This instruction writes vvp_vector4_t values to port-1 of the
|
||||
* target signal.
|
||||
*/
|
||||
bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_net_t*net = cp->net;
|
||||
unsigned base = cp->bit_idx[0];
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
|
||||
/* Collect the thread bits into a vector4 item. */
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
|
||||
|
||||
/* set the value into port 1 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 1);
|
||||
vvp_send_vec4(ptr, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_CMPS(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned eq = 1;
|
||||
|
|
@ -879,6 +928,21 @@ bool of_CVT_VR(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implements the %deassign instruction. All we do is write a
|
||||
* long(1) to port-3 of the addressed net. This turns off an active
|
||||
* continuous assign activated by %cassign/v
|
||||
*/
|
||||
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_net_t*net = cp->net;
|
||||
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
vvp_send_long(ptr, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_DELAY(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
//printf("thread %p: %%delay %lu\n", thr, cp->number);
|
||||
|
|
@ -1566,13 +1630,6 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool of_LOAD(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
thr_put_bit(thr, cp->bit_idx[0], functor_get(cp->iptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
|
|
@ -1582,7 +1639,15 @@ bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
/*
|
||||
* Load net/indexed.
|
||||
* %load/nx <bit>, <vpi-label>, <idx> ; Load net/indexed.
|
||||
*
|
||||
* cp->bit_idx[0] contains the <bit> value, an index into the thread
|
||||
* bit register.
|
||||
*
|
||||
* cp->bin_idx[1] is the <idx> value from the words array.
|
||||
*
|
||||
* cp->handle is the linked reference to the __vpiSignal that we are
|
||||
* to read from.
|
||||
*/
|
||||
bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
|
|
@ -1595,21 +1660,47 @@ bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
unsigned idx = thr->words[cp->bit_idx[1]].w_int;
|
||||
|
||||
vvp_ipoint_t ptr = vvp_fvector_get(sig->bits, idx);
|
||||
thr_put_bit(thr, cp->bit_idx[0], functor_get(ptr));
|
||||
vvp_fun_signal*fun = dynamic_cast<vvp_fun_signal*>(sig->node->fun);
|
||||
assert(sig != 0);
|
||||
|
||||
vvp_bit4_t val = fun->value(idx);
|
||||
thr_put_bit(thr, cp->bit_idx[0], val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* %load/v <bit>, <label>, <wid>
|
||||
*
|
||||
* Implement the %load/v instruction. Load the vector value of the
|
||||
* requested width from the <label> functor starting in the thread bit
|
||||
* <bit>.
|
||||
*
|
||||
* The <bit> value is the destination in the thread vector store, and
|
||||
* is in cp->bit_idx[0].
|
||||
*
|
||||
* The <wid> value is the expected with of the vector, and is in
|
||||
* cp->bit_idx[1].
|
||||
*
|
||||
* The functor to read from is the vvp_net_t object pointed to by the
|
||||
* cp->net pointer.
|
||||
*/
|
||||
bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
assert(cp->bit_idx[1] > 0);
|
||||
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
vvp_net_t*net = cp->net;
|
||||
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
thr_put_bit(thr, bit, functor_get(iptr));
|
||||
/* For the %load to work, the functor must actually be a
|
||||
signal functor. Only signals save their vector value. */
|
||||
vvp_fun_signal*sig = dynamic_cast<vvp_fun_signal*> (net->fun);
|
||||
assert(sig);
|
||||
|
||||
for (unsigned idx = 0; idx < wid; idx += 1, bit += 1) {
|
||||
vvp_bit4_t val = sig->value(idx);
|
||||
thr_put_bit(thr, bit, val);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1633,8 +1724,12 @@ bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
|
|||
assert(cp->bit_idx[0] >= 4);
|
||||
assert(cp->bit_idx[1] < 4);
|
||||
|
||||
#if 0
|
||||
vvp_ipoint_t ptr = ipoint_index(cp->iptr, thr->words[cp->bit_idx[1]].w_int);
|
||||
thr_put_bit(thr, cp->bit_idx[0], functor_get(ptr));
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement %%load/x\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2429,14 +2524,6 @@ bool of_NOR(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
|
||||
|
||||
bool of_SET(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
|
||||
functor_set(cp->iptr, bit_val, strong_values[bit_val], true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned char val = thr_get_bit(thr, cp->bit_idx[0]);
|
||||
|
|
@ -2445,26 +2532,30 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implements the "%set/v <label>, <bit>, <wid>" instruction.
|
||||
*
|
||||
* The <label> is a reference to a vvp_net_t object, and it is in
|
||||
* cp->net.
|
||||
*
|
||||
* The <bit> is the thread bit address, and is in cp->bin_idx[0].
|
||||
*
|
||||
* The <wid> is the width of the vector I'm to make, and is in
|
||||
* cp->bin_idx[1].
|
||||
*/
|
||||
bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[1] > 0);
|
||||
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
if (bit >= 4) {
|
||||
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
|
||||
unsigned char bit_val = thr_get_bit(thr, bit);
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
functor_set(iptr, bit_val, strong_values[bit_val], true);
|
||||
}
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
|
||||
} else {
|
||||
unsigned char bit_val = strong_values[bit];
|
||||
/* Make a vector of the desired width. */
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
/* set the value into port 0 of the destination. */
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
vvp_send_vec4(ptr, value);
|
||||
|
||||
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1) {
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
functor_set(iptr, bit, bit_val, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2502,12 +2593,16 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
if ((unsigned)idx > cp->bit_idx[1])
|
||||
return true;
|
||||
|
||||
#if 0
|
||||
/* Form the functor pointer from the base pointer and the
|
||||
index from the index register. */
|
||||
vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx);
|
||||
|
||||
/* Set the value. */
|
||||
functor_set(itmp, bit_val, strong_values[bit_val], true);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement %%set/x0\n");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2527,12 +2622,16 @@ bool of_SET_X0_X(vthread_t thr, vvp_code_t cp)
|
|||
if (idx > lim)
|
||||
return true;
|
||||
|
||||
#if 0
|
||||
/* Form the functor pointer from the base pointer and the
|
||||
index from the index register. */
|
||||
vvp_ipoint_t itmp = ipoint_index(cp->iptr, idx);
|
||||
|
||||
/* Set the value. */
|
||||
functor_set(itmp, bit_val, strong_values[bit_val], true);
|
||||
#else
|
||||
fprintf(stderr, "XXXX forgot how to implement %%set/x0/x\n");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2727,19 +2826,25 @@ bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
|
|||
return schedule_finished()? false : true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the wait by locating the functor for the event, and
|
||||
* adding this thread to the threads list for the event.
|
||||
/* %wait <label>;
|
||||
* Implement the wait by locating the vvp_net_T for the event, and
|
||||
* adding this thread to the threads list for the event. The some
|
||||
* argument is the reference to the functor to wait for. This must be
|
||||
* an event object of some sort.
|
||||
*/
|
||||
bool of_WAIT(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(! thr->waiting_for_event);
|
||||
thr->waiting_for_event = 1;
|
||||
waitable_hooks_s* ep = dynamic_cast<waitable_hooks_s*>(functor_index(cp->iptr));
|
||||
|
||||
vvp_net_t*net = cp->net;
|
||||
/* Get the functor as a waitable_hooks_s object. */
|
||||
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (net->fun);
|
||||
assert(ep);
|
||||
/* Add this thread to the list in the event. */
|
||||
thr->wait_next = ep->threads;
|
||||
ep->threads = thr;
|
||||
|
||||
/* Return false to suspend this thread. */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2874,6 +2979,11 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.123 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.122 2004/10/04 01:11:00 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue