Use PartSelect/PV and VP to handle part selects through ports.

This commit is contained in:
steve 2005-01-09 20:16:00 +00:00
parent 6c711ee4d8
commit 9e94afe399
12 changed files with 475 additions and 310 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.67 2004/12/29 23:55:43 steve Exp $" #ident "$Id: PExpr.h,v 1.68 2005/01/09 20:16:00 steve Exp $"
#endif #endif
# include <string> # include <string>
@ -276,6 +276,9 @@ class PEIdent : public PExpr {
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope, NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const; NetMemory*mem) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const;
}; };
class PENumber : public PExpr { class PENumber : public PExpr {
@ -503,6 +506,9 @@ class PECallFunction : public PExpr {
/* /*
* $Log: PExpr.h,v $ * $Log: PExpr.h,v $
* Revision 1.68 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.67 2004/12/29 23:55:43 steve * Revision 1.67 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.151 2004/12/29 23:55:43 steve Exp $" #ident "$Id: design_dump.cc,v 1.152 2005/01/09 20:16:00 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -356,7 +356,19 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
void NetPartSelect::dump_node(ostream&o, unsigned ind) const void NetPartSelect::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "NetPartSelect: " const char*pt = "";
switch (dir_) {
case VP:
pt = "VP";
break;
case PV:
pt = "PV";
break;
case BI:
pt = "BI";
break;
}
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
<< name() << " off=" << off_ << " wid=" << wid_ <<endl; << name() << " off=" << off_ << " wid=" << wid_ <<endl;
dump_node_pins(o, ind+4); dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4); dump_obj_attr(o, ind+4);
@ -1097,6 +1109,9 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $Log: design_dump.cc,v $
* Revision 1.152 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.151 2004/12/29 23:55:43 steve * Revision 1.151 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.139 2004/12/11 02:31:25 steve Exp $" #ident "$Id: elab_net.cc,v 1.140 2005/01/09 20:16:00 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1557,76 +1557,33 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
assert(sig); assert(sig);
if (msb_ && lsb_) { /* Catch the case of a non-constant bit select. That should be
handled elsewhere. */
if (msb_ && !lsb_) {
verinum*mval = msb_->eval_const(des, scope); verinum*mval = msb_->eval_const(des, scope);
if (mval == 0) { if (mval == 0) {
cerr << msb_->get_line() << ": error: unable to " return elaborate_net_bitmux_(des, scope, sig, rise,
"evaluate constant MSB expression: " << *msb_ << fall, decay, drive0, drive1);
endl;
des->errors += 1;
return 0;
} }
verinum*lval = lsb_->eval_const(des, scope); delete mval;
if (lval == 0) { }
cerr << lsb_->get_line() << ": error: unable to "
"evaluate constant LSB expression: " << *lsb_ <<
endl;
delete mval;
des->errors += 1;
return 0;
}
assert(mval); unsigned midx, lidx;
assert(lval); if (! eval_part_select_(des, scope, sig, midx, lidx))
return 0;
long mbit = mval->as_long(); unsigned part_count = midx-lidx+1;
long lbit = lval->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) && sig->sb_is_valid(lbit))) {
cerr << get_line() << ": error: bit/part select ["
<< mbit << ":" << lbit
<< "] out of range for " << sig->name() << endl;
des->errors += 1;
return sig;
}
unsigned midx = sig->sb_to_idx(mbit);
unsigned lidx = sig->sb_to_idx(lbit);
/* This is a part select, create a new NetNet object
that connects to just the desired parts of the
identifier. Make sure the NetNet::Type is compatible
with the sig type.
Be careful to check the bit ordering. If the msb is
less significant then the msb, then the source is
broken. I can hack it in order to go on, but report
an error. */
if (midx < lidx) {
cerr << get_line() << ": error: part select "
<< sig->name() << "[" << mval->as_long() << ":"
<< lval->as_long() << "] "
<< "has bit order reversed." << endl;
des->errors += 1;
unsigned tmp = midx;
midx = lidx;
lidx = tmp;
}
unsigned part_count = midx-lidx+1;
if (part_count != sig->vector_width()) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate part select " cerr << get_line() << ": debug: Elaborate part select "
<< sig->name() << "["<<mbit<<":"<<lbit<<"]" << endl; << sig->name() << "[base="<<lidx
<< " wid=" << part_count << "]" << endl;
} }
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count); NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count,
NetPartSelect::VP);
ps->set_line(*sig); ps->set_line(*sig);
des->add_node(ps); des->add_node(ps);
@ -1636,48 +1593,9 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
connect(tmp->pin(0), ps->pin(0)); connect(tmp->pin(0), ps->pin(0));
sig = tmp; sig = tmp;
} else if (msb_) {
verinum*mval = msb_->eval_const(des, scope);
if (mval == 0) {
return elaborate_net_bitmux_(des, scope, sig, rise,
fall, decay, drive0, drive1);
}
assert(mval);
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;
return sig;
}
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;
} }
return sig; return sig;
} }
@ -1804,7 +1722,8 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) { for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
unsigned wid = nets[idx]->vector_width(); unsigned wid = nets[idx]->vector_width();
unsigned off = width - wid; unsigned off = width - wid;
NetPartSelect*ps = new NetPartSelect(osig, off, wid); NetPartSelect*ps = new NetPartSelect(osig, off, wid,
NetPartSelect::VP);
des->add_node(ps); des->add_node(ps);
connect(ps->pin(1), osig->pin(0)); connect(ps->pin(1), osig->pin(0));
@ -1819,6 +1738,79 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
return osig; return osig;
} }
/*
* This private method evaluates the part selects (if any) for the
* signal. The sig argument is the NetNet already located for the
* PEIdent name. The midx and lidx arguments are loaded with the
* results, which may be the whole vector, or a single bit, or
* anything in between. The values are in canonical indices.
*/
bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const
{
if (msb_ && lsb_) {
verinum*mval = msb_->eval_const(des, scope);
assert(mval);
verinum*lval = lsb_->eval_const(des, scope);
assert(lval);
midx = sig->sb_to_idx(mval->as_long());
lidx = sig->sb_to_idx(lval->as_long());
/* Detect reversed indices of a part select. */
if (lidx > midx) {
cerr << get_line() << ": error: Part select "
<< sig->name() << "[" << mval->as_long() << ":"
<< lval->as_long() << "] indices reversed." << endl;
cerr << get_line() << ": : Did you mean "
<< sig->name() << "[" << lval->as_long() << ":"
<< mval->as_long() << "]?" << endl;
unsigned tmp = midx;
midx = lidx;
lidx = tmp;
des->errors += 1;
}
/* Detect a part select out of range. */
if (midx >= sig->vector_width()) {
cerr << get_line() << ": error: Part select "
<< sig->name() << "[" << mval->as_long() << ":"
<< lval->as_long() << "] out of range." << endl;
midx = sig->vector_width() - 1;
lidx = 0;
des->errors += 1;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, scope);
if (mval == 0) {
cerr << get_line() << ": index of " << path_ <<
" needs to be constant in this context." <<
endl;
des->errors += 1;
return false;
}
assert(mval);
midx = sig->sb_to_idx(mval->as_long());
if (midx >= sig->vector_width()) {
cerr << get_line() << ": error: Index " << sig->name()
<< "[" << mval->as_long() << "] out of range."
<< endl;
des->errors += 1;
midx = 0;
}
lidx = midx;
} else {
assert(msb_ == 0 && lsb_ == 0);
midx = sig->vector_width() - 1;
lidx = 0;
}
return true;
}
/* /*
* Identifiers in continuous assignment l-values are limited to wires * Identifiers in continuous assignment l-values are limited to wires
* and that ilk. Detect registers and memories here and report errors. * and that ilk. Detect registers and memories here and report errors.
@ -1895,65 +1887,37 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
sig->port_type(NetNet::PINOUT); sig->port_type(NetNet::PINOUT);
} }
if (msb_ && lsb_) { unsigned midx, lidx;
/* Detect a part select. Evaluate the bits and elaborate if (! eval_part_select_(des, scope, sig, midx, lidx))
the l-value by creating a sub-net that links to just return 0;
the right pins. */
verinum*mval = msb_->eval_const(des, scope);
assert(mval);
verinum*lval = lsb_->eval_const(des, scope);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) { unsigned subnet_wid = midx-lidx+1;
unsigned subnet_wid = midx-lidx+1;
if (subnet_wid > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
NetSubnet*tmp = new NetSubnet(sig, lidx, subnet_wid); /* If the desired l-value vector is narrower then the
signal itself, then use a NetPartSelect node to
arrange for connection to the desired bits. All this
can be skipped if the desired with matches the
original vector. */
sig = tmp; if (subnet_wid != sig->vector_width()) {
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Elaborate lnet part select "
<< sig->name()
<< "[base=" << lidx
<< " wid=" << subnet_wid <<"]"
<< endl;
} else { NetNet*subsig = new NetNet(sig->scope(),
unsigned subnet_wid = midx-lidx+1; sig->scope()->local_symbol(),
NetNet::WIRE, subnet_wid);
if (subnet_wid > sig->pin_count()) { NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
cerr << get_line() << ": error: " NetPartSelect::PV);
<< "part select out of range for " des->add_node(sub);
<< sig->name() << "." << endl; connect(sub->pin(0), subsig->pin(0));
des->errors += 1;
return sig;
}
NetSubnet*tmp = new NetSubnet(sig, lidx, subnet_wid); sig = subsig;
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, scope);
if (mval == 0) {
cerr << get_line() << ": error: index of " << path_ <<
" needs to be constant in l-value of assignment." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
sig = tmp;
} }
return sig; return sig;
@ -1962,7 +1926,10 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
/* /*
* This method is used to elaborate identifiers that are ports to a * This method is used to elaborate identifiers that are ports to a
* scope. The scope is presumed to be that of the module that has the * scope. The scope is presumed to be that of the module that has the
* port. * port. This elaboration is done inside the module, and is only done
* to PEIdent objects. This method is used by elaboration of a module
* instantiation (PGModule::elaborate_mod_) to get NetNet objects for
* the port.
*/ */
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
{ {
@ -1974,6 +1941,8 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
return 0; return 0;
} }
/* Check the port_type of the signal to make sure it is really
a port, and its direction is resolved. */
switch (sig->port_type()) { switch (sig->port_type()) {
case NetNet::PINPUT: case NetNet::PINPUT:
case NetNet::POUTPUT: case NetNet::POUTPUT:
@ -2004,64 +1973,22 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
return 0; return 0;
} }
unsigned midx;
unsigned lidx;
if (msb_ && lsb_) { /* Evaluate the part/bit select expressions, to get the part
/* Detect a part select. Evaluate the bits and elaborate select of the signal that attaches to the port. Also handle
the l-value by creating a sub-net that links to just range and direction checking here. */
the right pins. */
verinum*mval = msb_->eval_const(des, scope);
assert(mval);
verinum*lval = lsb_->eval_const(des, scope);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) { if (! eval_part_select_(des, scope, sig, midx, lidx))
unsigned part_count = midx-lidx+1; return 0;
if (part_count > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
NetSubnet*tmp = new NetSubnet(sig, lidx, part_count);
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
connect(tmp->pin(idx-lidx), sig->pin(idx));
sig = tmp; unsigned swid = midx - lidx + 1;
} else { if (swid < sig->vector_width()) {
/* XXXX Signals reversed?? */ cerr << get_line() << ": XXXX: Forgot to implement part select"
unsigned part_count = lidx-midx+1; << " of signal port." << endl;
assert(part_count <= sig->pin_count());
NetSubnet*tmp = new NetSubnet(sig, midx, part_count);
for (unsigned idx = midx ; idx >= lidx ; idx -= 1)
connect(tmp->pin(idx-midx), sig->pin(idx));
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, scope);
if (mval == 0) {
cerr << get_line() << ": index of " << path_ <<
" needs to be constant in port context." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
} }
return sig; return sig;
@ -2560,6 +2487,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $Log: elab_net.cc,v $
* Revision 1.140 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.139 2004/12/11 02:31:25 steve * Revision 1.139 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead * Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes * of single bits. Make the ivl, tgt-vvp and vvp initial changes

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.312 2004/12/29 23:55:43 steve Exp $" #ident "$Id: elaborate.cc,v 1.313 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -312,7 +312,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
instance_width = count; instance_width = count;
count = 1; count = 1;
if (debug_elaborate) if (debug_elaborate && instance_width != 1)
cerr << get_line() << ": debug: PGBuiltin: " cerr << get_line() << ": debug: PGBuiltin: "
"Collapsed gate array into single wide " "Collapsed gate array into single wide "
"(" << instance_width << ") instance." << endl; "(" << instance_width << ") instance." << endl;
@ -507,7 +507,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
} else for (unsigned gdx = 0 ; gdx < count ; gdx += 1) { } else for (unsigned gdx = 0 ; gdx < count ; gdx += 1) {
/* Use part selects to get the bits /* Use part selects to get the bits
connected to the inputs of out gate. */ connected to the inputs of out gate. */
NetPartSelect*tmp1 = new NetPartSelect(sig, gdx, 1); NetPartSelect*tmp1 = new NetPartSelect(sig, gdx, 1,
NetPartSelect::VP);
tmp1->set_line(*this); tmp1->set_line(*this);
des->add_node(tmp1); des->add_node(tmp1);
connect(tmp1->pin(1), sig->pin(0)); connect(tmp1->pin(1), sig->pin(0));
@ -603,7 +604,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} else { } else {
/* Otherwise, this is a positional list of fort /* Otherwise, this is a positional list of port
connections. In this case, the port count must be connections. In this case, the port count must be
right. Check that is is, the get the pin list. */ right. Check that is is, the get the pin list. */
@ -685,8 +686,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
svector<PEIdent*> mport = rmod->get_port(idx); svector<PEIdent*> mport = rmod->get_port(idx);
svector<NetNet*>prts (mport.count() * instance.count()); svector<NetNet*>prts (mport.count() * instance.count());
// Count the internal pins of the port. // Count the internal vector bits of the port.
unsigned prts_pin_count = 0; unsigned prts_vector_width = 0;
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) { for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
NetScope*inst_scope = instance[inst]; NetScope*inst_scope = instance[inst];
@ -702,21 +703,21 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
continue; continue;
assert(prts[lbase + ldx]); assert(prts[lbase + ldx]);
prts_pin_count += prts[lbase + ldx]->pin_count(); prts_vector_width += prts[lbase + ldx]->vector_width();
} }
} }
// If I find that the port in unconnected inside the // If I find that the port is unconnected inside the
// module, then there is nothing to connect. Skip the // module, then there is nothing to connect. Skip the
// argument. // argument.
if (prts_pin_count == 0) { if (prts_vector_width == 0) {
continue; continue;
} }
// We know by design that each instance has the same // We know by design that each instance has the same
// width port. Therefore, the prts_pin_count must be an // width port. Therefore, the prts_pin_count must be an
// even multiple of the instance count. // even multiple of the instance count.
assert(prts_pin_count % instance.count() == 0); assert(prts_vector_width % instance.count() == 0);
// Elaborate the expression that connects to the // Elaborate the expression that connects to the
// module[s] port. sig is the thing outside the module // module[s] port. sig is the thing outside the module
@ -744,12 +745,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
array, then let the net determine it's own array, then let the net determine it's own
width. We use that, then, to decide how to hook width. We use that, then, to decide how to hook
it up. */ it up. */
unsigned desired_pin_count = prts_pin_count; unsigned desired_vector_width = prts_vector_width;
if (instance.count() != 1) if (instance.count() != 1)
desired_pin_count = 0; desired_vector_width = 0;
sig = pins[idx]->elaborate_net(des, scope, sig = pins[idx]->elaborate_net(des, scope,
desired_pin_count, desired_vector_width,
0, 0, 0); 0, 0, 0);
if (sig == 0) { if (sig == 0) {
cerr << pins[idx]->get_line() cerr << pins[idx]->get_line()
@ -771,12 +772,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
/* If we are working with an instance array, then the /* If we are working with an instance array, then the
signal width must match the port width exactly. */ signal width must match the port width exactly. */
if ((instance.count() != 1) if ((instance.count() != 1)
&& (sig->pin_count() != prts_pin_count) && (sig->vector_width() != prts_vector_width)
&& (sig->pin_count() != prts_pin_count/instance.count())) { && (sig->vector_width() != prts_vector_width/instance.count())) {
cerr << pins[idx]->get_line() << ": error: " cerr << pins[idx]->get_line() << ": error: "
<< "Port expression width " << sig->pin_count() << "Port expression width " << sig->vector_width()
<< " does not match expected width " << prts_pin_count << " does not match expected width "<< prts_vector_width
<< " or " << (prts_pin_count/instance.count()) << " or " << (prts_vector_width/instance.count())
<< "." << endl; << "." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
@ -786,20 +787,20 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// not, they are different widths. Note that idx is 0 // not, they are different widths. Note that idx is 0
// based, but users count parameter positions from 1. // based, but users count parameter positions from 1.
if ((instance.count() == 1) if ((instance.count() == 1)
&& (prts_pin_count != sig->pin_count())) { && (prts_vector_width != sig->vector_width())) {
cerr << get_line() << ": warning: Port " << (idx+1) cerr << get_line() << ": warning: Port " << (idx+1)
<< " (" << rmod->ports[idx]->name << ") of " << " (" << rmod->ports[idx]->name << ") of "
<< type_ << " expects " << prts_pin_count << << type_ << " expects " << prts_vector_width <<
" bits, got " << sig->pin_count() << "." << endl; " bits, got " << sig->vector_width() << "." << endl;
if (prts_pin_count > sig->pin_count()) { if (prts_vector_width > sig->vector_width()) {
cerr << get_line() << ": : Leaving " cerr << get_line() << ": : Leaving "
<< (prts_pin_count-sig->pin_count()) << (prts_vector_width-sig->vector_width())
<< " high bits of the port unconnected." << " high bits of the port unconnected."
<< endl; << endl;
} else { } else {
cerr << get_line() << ": : Leaving " cerr << get_line() << ": : Leaving "
<< (sig->pin_count()-prts_pin_count) << (sig->vector_width()-prts_vector_width)
<< " high bits of the expression dangling." << " high bits of the expression dangling."
<< endl; << endl;
} }
@ -815,41 +816,85 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// the number of connections to make. // the number of connections to make.
// Connect this many of the port pins. If the expression // Connect this many of the port pins. If the expression
// is too small, the reduce the number of connects. // is too small, then reduce the number of connects.
unsigned ccount = prts_pin_count; unsigned ccount = prts_vector_width;
if (instance.count() == 1 && sig->pin_count() < ccount) if (instance.count() == 1 && sig->vector_width() < ccount)
ccount = sig->pin_count(); ccount = sig->vector_width();
// The spin_modulus is the width of the signal (not the // The spin_modulus is the width of the signal (not the
// port) if this is an instance array. This causes // port) if this is an instance array. This causes
// signals wide enough for a single instance to be // signals wide enough for a single instance to be
// connected to all the instances. // connected to all the instances.
unsigned spin_modulus = prts_pin_count; unsigned spin_modulus = prts_vector_width;
if (instance.count() != 1) if (instance.count() != 1)
spin_modulus = sig->pin_count(); spin_modulus = sig->vector_width();
// Now scan the concatenation that makes up the port, // Now scan the concatenation that makes up the port,
// connecting pins until we run out of port pins or sig // connecting pins until we run out of port pins or sig
// pins. // pins. The sig object is the NetNet that is connected
// to the port from the outside, and the prts object is
// an array of signals to be connected to the sig.
NetConcat*ctmp;
unsigned spin = 0; unsigned spin = 0;
for (unsigned ldx = prts.count() ; ldx > 0 ; ldx -= 1) {
unsigned cnt = prts[ldx-1]->pin_count(); if (prts.count() == 1) {
if (cnt > ccount)
cnt = ccount; // The simplest case, there are no
for (unsigned p = 0 ; p < cnt ; p += 1) { // parts/concatenations on the inside of the
connect(sig->pin(spin%spin_modulus), // module, so the port and sig need simply be
prts[ldx-1]->pin(p)); // connected directly.
ccount -= 1; connect(prts[0]->pin(0), sig->pin(0));
spin += 1;
} else if (sig->vector_width() == prts_vector_width/instance.count()) {
// The signal width is exactly the width of a
// single instance of the port. In this case,
// connect the sig to all the ports identically.
for (unsigned ldx = 0 ; ldx < prts.count() ; ldx += 1)
connect(prts[ldx]->pin(0), sig->pin(0));
} else switch (prts[0]->port_type()) {
case NetNet::POUTPUT:
ctmp = new NetConcat(scope, scope->local_symbol(),
prts_vector_width,
prts.count());
des->add_node(ctmp);
connect(ctmp->pin(0), sig->pin(0));
for (unsigned ldx = 0 ; ldx < prts.count() ; ldx += 1) {
connect(ctmp->pin(ldx+1),
prts[prts.count()-ldx-1]->pin(0));
} }
if (ccount == 0) break;
break;
case NetNet::PINPUT:
for (unsigned ldx = 0 ; ldx < prts.count() ; ldx += 1) {
NetNet*sp = prts[prts.count()-ldx-1];
NetPartSelect*ptmp = new NetPartSelect(sig, spin,
sp->vector_width(),
NetPartSelect::VP);
des->add_node(ptmp);
connect(ptmp->pin(0), sp->pin(0));
spin += sp->vector_width();
}
break;
case NetNet::PINOUT:
cerr << get_line() << ": XXXX: "
<< "Forgot how to bind input ports!" << endl;
des->errors += 1;
break;
case NetNet::PIMPLICIT:
cerr << get_line() << ": internal error: "
<< "Unexpected IMPLICIT port" << endl;
des->errors += 1;
break;
case NetNet::NOT_A_PORT:
cerr << get_line() << ": internal error: "
<< "Unexpected NOT_A_PORT port." << endl;
des->errors += 1;
break;
} }
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(sig))
delete tmp;
} }
} }
@ -2845,6 +2890,9 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.313 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.312 2004/12/29 23:55:43 steve * Revision 1.312 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.130 2004/12/29 23:55:43 steve Exp $" #ident "$Id: ivl_target.h,v 1.131 2005/01/09 20:16:01 steve Exp $"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -232,7 +232,8 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_MOD = 13, IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4, IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5, IVL_LPM_MUX = 5,
IVL_LPM_PART = 15, /* part select */ IVL_LPM_PART_VP= 15, /* part select: vector to part */
IVL_LPM_PART_PV= 17, /* part select: part written to vector */
IVL_LPM_SHIFTL = 6, IVL_LPM_SHIFTL = 6,
IVL_LPM_SHIFTR = 7, IVL_LPM_SHIFTR = 7,
IVL_LPM_SUB = 8, IVL_LPM_SUB = 8,
@ -733,6 +734,25 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* The ivl_lpm_data function returns the connections for the inputs to * The ivl_lpm_data function returns the connections for the inputs to
* the concatentation. The ivl_lpm_size function returns the number of * the concatentation. The ivl_lpm_size function returns the number of
* inputs help by the device. * inputs help by the device.
*
* - Part Select (IVL_LPM_PART_VP and IVL_LPM_PART_PV)
* There are two part select devices, one that extracts a part from a
* vector, and another that writes a part of a vector. The _VP is
* Vector-to-Part, and _PV is Part-to-Vector. The _VP form is meant to
* model part/bin selects in r-value expressions, where the _PV from
* is meant to model part selects in l-value nets.
*
* In both cases, ivl_lpm_data is the input pin, and ivl_lpm_q is the
* output. In the case of the _VP device, the vector is input and the
* part is the output. In the case of the _PV device, the part is the
* input and the vector is the output.
*
* Also in both cases, the width of the device is the width of the
* part. In the _VP case, this is obvious as the output nexus has the
* part width. In the _PV case, this is a little less obvious, but
* still correct. The output being written to the wider vector is
* indeed the width of the part, even though it is written to a wider
* gate. The target will need to handle this case specially.
*/ */
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
@ -1393,6 +1413,9 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $Log: ivl_target.h,v $
* Revision 1.131 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.130 2004/12/29 23:55:43 steve * Revision 1.130 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.14 2004/02/18 17:11:56 steve Exp $" #ident "$Id: net_link.cc,v 1.15 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -364,7 +364,7 @@ const char* Nexus::name() const
} }
assert(sig); assert(sig);
ostringstream tmp; ostringstream tmp;
tmp << sig->name(); tmp << sig->scope()->name() << "." << sig->name();
if (sig->pin_count() > 1) if (sig->pin_count() > 1)
tmp << "<" << pin << ">"; tmp << "<" << pin << ">";
@ -499,6 +499,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/* /*
* $Log: net_link.cc,v $ * $Log: net_link.cc,v $
* Revision 1.15 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.14 2004/02/18 17:11:56 steve * Revision 1.14 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.228 2004/12/29 23:55:43 steve Exp $" #ident "$Id: netlist.cc,v 1.229 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -393,7 +393,7 @@ long NetNet::msb() const
return msb_; return msb_;
} }
long NetNet::vector_width() const unsigned long NetNet::vector_width() const
{ {
if (msb_ > lsb_) if (msb_ > lsb_)
return msb_ - lsb_ + 1; return msb_ - lsb_ + 1;
@ -466,17 +466,30 @@ NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
set_line(*sig); set_line(*sig);
} }
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid) NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
NetPartSelect::dir_t dir)
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2), : NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
off_(off), wid_(wid) off_(off), wid_(wid), dir_(dir)
{ {
connect(pin(1), sig->pin(0)); connect(pin(1), sig->pin(0));
set_line(*sig); set_line(*sig);
pin(0).set_dir(Link::OUTPUT); switch (dir_) {
pin(1).set_dir(Link::INPUT); case NetPartSelect::VP:
pin(0).set_name(perm_string::literal("O"), 0); pin(0).set_dir(Link::OUTPUT);
pin(1).set_name(perm_string::literal("I"), 0); pin(1).set_dir(Link::INPUT);
break;
case NetPartSelect::PV:
pin(0).set_dir(Link::INPUT);
pin(1).set_dir(Link::OUTPUT);
break;
case NetPartSelect::BI:
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
break;
}
pin(0).set_name(perm_string::literal("Part"), 0);
pin(1).set_name(perm_string::literal("Vect"), 0);
} }
NetPartSelect::~NetPartSelect() NetPartSelect::~NetPartSelect()
@ -493,6 +506,11 @@ unsigned NetPartSelect::base() const
return off_; return off_;
} }
NetPartSelect::dir_t NetPartSelect::dir() const
{
return dir_;
}
NetProc::NetProc() NetProc::NetProc()
: next_(0) : next_(0)
{ {
@ -2326,6 +2344,9 @@ const NetProc*NetTaskDef::proc() const
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.229 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.228 2004/12/29 23:55:43 steve * Revision 1.228 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.323 2004/12/29 23:55:43 steve Exp $" #ident "$Id: netlist.h,v 1.324 2005/01/09 20:16:01 steve Exp $"
#endif #endif
/* /*
@ -400,7 +400,7 @@ class NetNet : public NetObj {
reg [1:8] has 8 bits, msb==1 and lsb==8. */ reg [1:8] has 8 bits, msb==1 and lsb==8. */
long msb() const; long msb() const;
long lsb() const; long lsb() const;
long vector_width() const; unsigned long vector_width() const;
/* This method converts a signed index (the type that might be /* This method converts a signed index (the type that might be
found in the verilog source) to a pin number. It accounts found in the verilog source) to a pin number. It accounts
@ -591,6 +591,10 @@ class NetCompare : public NetNode {
* remaining pins are the input that are combined to make the * remaining pins are the input that are combined to make the
* output. It is seperated out because it it generally a special case * output. It is seperated out because it it generally a special case
* for the code generators. * for the code generators.
*
* When constructing the node, the width is the vector_width of the
* output, and the cnt is the number of pins. (1 + the number of input
* vectors.)
*/ */
class NetConcat : public NetNode { class NetConcat : public NetNode {
@ -1163,19 +1167,45 @@ class NetSubnet : public NetNet {
}; };
/* /*
* The NetPartSelect device represents an r-value part select of a * The NetPartSelect device represents a netlist part select of a
* signal. The output (pin 0) is a vector that is a part select of the * signal vector. Pin 0 is a vector that is a part select of pin 1,
* input (pin 1). The part to be selected is the canonical (0-based) * which connected to the NetNet of the signal being selected from.
* offset and the specified number of bits (wid). *
* The part to be selected is the canonical (0-based) offset and the
* specified number of bits (wid).
*
* The NetPartSelect can be output from the signal (i.e. reading a
* part), input into the signal, or bi-directional. The DIR method
* gives the type of the node.
*
* VP (Vector-to-Part)
* Output pin 0 is the part select, and input pin 1 is connected to
* the NetNet object.
*
* PV (Part-to-Vector)
* Output pin 1 is connected to the NetNet, and input pin 0 is the
* part select. In this case, the node is driving the NetNet.
*
* BI (BI-directional)
* Pin 0 is the part select and pin 1 is connected to the NetNet, but
* the ports are intended to be bi-directional.
*
* Note that whatever the direction that data is intended to flow,
* pin-0 is the part select and pin-1 is connected to the NetNet.
*/ */
class NetPartSelect : public NetNode { class NetPartSelect : public NetNode {
public: public:
explicit NetPartSelect(NetNet*sig, unsigned off, unsigned wid); // enum for the device direction
enum dir_t { VP, PV, BI };
explicit NetPartSelect(NetNet*sig,
unsigned off, unsigned wid, dir_t dir);
~NetPartSelect(); ~NetPartSelect();
unsigned width() const;
unsigned base() const; unsigned base() const;
unsigned width() const;
dir_t dir() const;
virtual void dump_node(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const;
bool emit_node(struct target_t*tgt) const; bool emit_node(struct target_t*tgt) const;
@ -1183,6 +1213,7 @@ class NetPartSelect : public NetNode {
private: private:
unsigned off_; unsigned off_;
unsigned wid_; unsigned wid_;
dir_t dir_;
}; };
/* /*
@ -3380,6 +3411,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.324 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.323 2004/12/29 23:55:43 steve * Revision 1.323 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.112 2004/12/29 23:55:43 steve Exp $" #ident "$Id: t-dll-api.cc,v 1.113 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -682,7 +682,8 @@ extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
{ {
assert(net); assert(net);
switch (net->type) { switch (net->type) {
case IVL_LPM_PART: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
return net->u_.part.base; return net->u_.part.base;
default: default:
assert(0); assert(0);
@ -789,7 +790,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(idx < net->u_.concat.inputs); assert(idx < net->u_.concat.inputs);
return net->u_.concat.pins[idx+1]; return net->u_.concat.pins[idx+1];
case IVL_LPM_PART: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
assert(idx == 0); assert(idx == 0);
return net->u_.part.a; return net->u_.part.a;
@ -939,7 +941,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
return net->u_.concat.pins[0]; return net->u_.concat.pins[0];
case IVL_LPM_PART: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
assert(idx == 0); assert(idx == 0);
return net->u_.part.q; return net->u_.part.q;
@ -1027,7 +1030,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return 0; return 0;
case IVL_LPM_CONCAT: // Concatenations are always unsigned case IVL_LPM_CONCAT: // Concatenations are always unsigned
return 0; return 0;
case IVL_LPM_PART: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
return net->u_.part.signed_flag; return net->u_.part.signed_flag;
default: default:
assert(0); assert(0);
@ -1079,7 +1083,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
return net->u_.ufunc.port_wid[0]; return net->u_.ufunc.port_wid[0];
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
return net->u_.concat.width; return net->u_.concat.width;
case IVL_LPM_PART: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
return net->u_.part.width; return net->u_.part.width;
default: default:
assert(0); assert(0);
@ -1963,6 +1968,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/* /*
* $Log: t-dll-api.cc,v $ * $Log: t-dll-api.cc,v $
* Revision 1.113 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.112 2004/12/29 23:55:43 steve * Revision 1.112 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.133 2004/12/29 23:55:43 steve Exp $" #ident "$Id: t-dll.cc,v 1.134 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1898,7 +1898,17 @@ bool dll_target::concat(const NetConcat*net)
bool dll_target::part_select(const NetPartSelect*net) bool dll_target::part_select(const NetPartSelect*net)
{ {
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_PART; switch (net->dir()) {
case NetPartSelect::VP:
obj->type = IVL_LPM_PART_VP;
break;
case NetPartSelect::PV:
obj->type = IVL_LPM_PART_PV;
break;
case NetPartSelect::BI:
assert(0); // XXXX Not supported yet
break;
}
obj->name = net->name(); // NetPartSelect names are permallocated. obj->name = net->name(); // NetPartSelect names are permallocated.
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
@ -1912,18 +1922,40 @@ bool dll_target::part_select(const NetPartSelect*net)
obj->u_.part.signed_flag = 0; obj->u_.part.signed_flag = 0;
const Nexus*nex; const Nexus*nex;
/* NetPartSelect:pin(0) is the output pin. */ switch (obj->type) {
nex = net->pin(0).nexus(); case IVL_LPM_PART_VP:
assert(nex->t_cookie()); /* 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();
/* 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();
break;
case IVL_LPM_PART_PV:
/* NetPartSelect:pin(1) is the output pin. */
nex = net->pin(1).nexus();
assert(nex->t_cookie());
obj->u_.part.q = (ivl_nexus_t) nex->t_cookie();
/* NetPartSelect:pin(0) is the input pin. */
nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.part.a = (ivl_nexus_t) nex->t_cookie();
break;
default:
assert(0);
}
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); 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); nexus_lpm_add(obj->u_.part.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
scope_add_lpm(obj->scope, obj); scope_add_lpm(obj->scope, obj);
@ -2207,6 +2239,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.134 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.133 2004/12/29 23:55:43 steve * Revision 1.133 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.94 2004/12/29 23:55:43 steve Exp $" #ident "$Id: stub.c,v 1.95 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -406,8 +406,17 @@ static void show_lpm(ivl_lpm_t net)
break; break;
} }
case IVL_LPM_PART: { case IVL_LPM_PART_VP: {
fprintf(out, " LPM_PART %s: <width=%u, base=%u, signed=%d>\n", fprintf(out, " LPM_PART_VP %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;
}
case IVL_LPM_PART_PV: {
fprintf(out, " LPM_PART_PV %s: <width=%u, base=%u, signed=%d>\n",
ivl_lpm_basename(net), ivl_lpm_basename(net),
width, ivl_lpm_base(net), ivl_lpm_signed(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, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
@ -584,13 +593,21 @@ static void show_signal(ivl_signal_t net)
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)]; const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
if ((sig = ivl_nexus_ptr_sig(ptr))) { if ((sig = ivl_nexus_ptr_sig(ptr))) {
fprintf(out, " %s[%u] (%s0, %s1)\n", fprintf(out, " SIG %s (%s0, %s1)",
ivl_signal_name(sig), ivl_signal_name(sig), dr0, dr1);
ivl_nexus_ptr_pin(ptr), dr0, dr1);
/* Only pin-0 of signals is used. If this is
something other then pin-0, report an error. */
if (ivl_nexus_ptr_pin(ptr) != 0)
fprintf(out, " (pin=%u, should be 0)",
ivl_nexus_ptr_pin(ptr));
fprintf(out, "\n");
} else if ((log = ivl_nexus_ptr_log(ptr))) { } else if ((log = ivl_nexus_ptr_log(ptr))) {
fprintf(out, " %s[%u] (%s0, %s1)\n", fprintf(out, " LOG %s.%s[%u] (%s0, %s1)\n",
ivl_logic_name(log), ivl_scope_name(ivl_logic_scope(log)),
ivl_logic_basename(log),
ivl_nexus_ptr_pin(ptr), dr0, dr1); ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) { } else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
@ -810,6 +827,9 @@ int target_design(ivl_design_t des)
/* /*
* $Log: stub.c,v $ * $Log: stub.c,v $
* Revision 1.95 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.94 2004/12/29 23:55:43 steve * Revision 1.94 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments, * Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force. * including assing, cassign and force.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.105 2004/12/29 23:52:09 steve Exp $" #ident "$Id: vvp_scope.c,v 1.106 2005/01/09 20:16:01 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -431,6 +431,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_RAM: case IVL_LPM_RAM:
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CONCAT:
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
case IVL_LPM_SUB: case IVL_LPM_SUB:
@ -438,7 +439,8 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_DIVIDE: case IVL_LPM_DIVIDE:
case IVL_LPM_MOD: case IVL_LPM_MOD:
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
case IVL_LPM_PART: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV: /* NOTE: This is onlt a partial driver. */
if (ivl_lpm_q(lpm, 0) == nex) { if (ivl_lpm_q(lpm, 0) == nex) {
sprintf(result, "L_%p", lpm); sprintf(result, "L_%p", lpm);
return result; return result;
@ -446,7 +448,6 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
break; break;
case IVL_LPM_CONCAT:
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT: case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_EQ:
@ -1299,9 +1300,7 @@ static void draw_lpm_concat(ivl_lpm_t net)
/* XXXX For now, only handle concatenation of 4 values. */ /* XXXX For now, only handle concatenation of 4 values. */
assert(icnt <= 4); assert(icnt <= 4);
fprintf(vvp_out, "L_%s.%s .concat [", fprintf(vvp_out, "L_%p .concat [", net);
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)));
for (idx = 0 ; idx < icnt ; idx += 1) { for (idx = 0 ; idx < icnt ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx); ivl_nexus_t nex = ivl_lpm_data(net, idx);
@ -1310,7 +1309,7 @@ static void draw_lpm_concat(ivl_lpm_t net)
} }
for ( ; idx < 4 ; idx += 1) for ( ; idx < 4 ; idx += 1)
fpritnf(vvp_out, " 0"); fprintf(vvp_out, " 0");
fprintf(vvp_out, "]"); fprintf(vvp_out, "]");
@ -1569,6 +1568,22 @@ static void draw_lpm_part(ivl_lpm_t net)
fprintf(vvp_out, ", %u, %u;\n", base, width); fprintf(vvp_out, ", %u, %u;\n", base, width);
} }
/*
* Handle a PART SELECT PV device. Generate a .part/pv node that
* includes the part input, and the geometry of the part.
*/
static void draw_lpm_part_pv(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned base = ivl_lpm_base(net);
unsigned signal_width = width_of_nexus(ivl_lpm_q(net,0));
fprintf(vvp_out, "L_%p .part/pv ", net);
draw_input_from_net(ivl_lpm_data(net, 0));
fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width);
}
static void draw_lpm_in_scope(ivl_lpm_t net) static void draw_lpm_in_scope(ivl_lpm_t net)
{ {
switch (ivl_lpm_type(net)) { switch (ivl_lpm_type(net)) {
@ -1585,10 +1600,14 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_add(net); draw_lpm_add(net);
return; return;
case IVL_LPM_PART: case IVL_LPM_PART_VP:
draw_lpm_part(net); draw_lpm_part(net);
return; return;
case IVL_LPM_PART_PV:
draw_lpm_part_pv(net);
return;
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
draw_lpm_concat(net); draw_lpm_concat(net);
return; return;
@ -1743,6 +1762,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/* /*
* $Log: vvp_scope.c,v $ * $Log: vvp_scope.c,v $
* Revision 1.106 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.105 2004/12/29 23:52:09 steve * Revision 1.105 2004/12/29 23:52:09 steve
* Generate code for the .concat functors, from NetConcat objects. * Generate code for the .concat functors, from NetConcat objects.
* Generate C<> constants of correct widths for functor arguments. * Generate C<> constants of correct widths for functor arguments.