Clarify msb/lsb in context of netlist. Properly

handle part selects in lval and rval of expressions,
 and document where the least significant bit goes
 in NetNet objects.
This commit is contained in:
steve 1999-09-13 03:10:59 +00:00
parent 6847dac5c2
commit 7a211b9136
3 changed files with 116 additions and 34 deletions

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
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: elaborate.cc,v 1.82 1999/09/12 01:16:51 steve Exp $" #ident "$Id: elaborate.cc,v 1.83 1999/09/13 03:10:59 steve Exp $"
#endif #endif
/* /*
@ -105,11 +105,17 @@ void PWire::elaborate(Design*des, const string&path) const
wtype = NetNet::REG; wtype = NetNet::REG;
unsigned wid = 1; unsigned wid = 1;
long lsb = 0, msb = 0;
if (msb_.count()) { if (msb_.count()) {
svector<long>mnum (msb_.count()); svector<long>mnum (msb_.count());
svector<long>lnum (msb_.count()); svector<long>lnum (msb_.count());
/* There may be multiple declarations of ranges, because
the symbol may have its range declared in i.e. input
and reg declarations. Calculate *all* the numbers
here. I will resolve the values later. */
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) { for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
verinum*mval = msb_[idx]->eval_const(des,path); verinum*mval = msb_[idx]->eval_const(des,path);
if (mval == 0) { if (mval == 0) {
@ -134,6 +140,8 @@ void PWire::elaborate(Design*des, const string&path) const
delete lval; delete lval;
} }
/* Make sure all the values for msb and lsb match by
value. If not, report an error. */
for (unsigned idx = 1 ; idx < msb_.count() ; idx += 1) { for (unsigned idx = 1 ; idx < msb_.count() ; idx += 1) {
if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) { if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) {
cerr << get_line() << ": Inconsistent width, " cerr << get_line() << ": Inconsistent width, "
@ -145,6 +153,8 @@ void PWire::elaborate(Design*des, const string&path) const
} }
} }
lsb = lnum[0];
msb = mnum[0];
if (mnum[0] > lnum[0]) if (mnum[0] > lnum[0])
wid = mnum[0] - lnum[0] + 1; wid = mnum[0] - lnum[0] + 1;
else else
@ -173,7 +183,7 @@ void PWire::elaborate(Design*des, const string&path) const
} else { } else {
NetNet*sig = new NetNet(path + "." + name_, wtype, wid); NetNet*sig = new NetNet(path + "." + name_, wtype, msb, lsb);
sig->set_line(*this); sig->set_line(*this);
sig->port_type(port_type_); sig->port_type(port_type_);
sig->set_attributes(attributes); sig->set_attributes(attributes);
@ -1255,14 +1265,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
verinum*msn = msb_->eval_const(des, path); verinum*msn = msb_->eval_const(des, path);
unsigned long lsv = lsn->as_ulong(); unsigned long lsv = lsn->as_ulong();
unsigned long msv = msn->as_ulong(); unsigned long msv = msn->as_ulong();
assert(msv >= lsv); unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
unsigned long wid = msv-lsv+1; assert(wid <= net->pin_count());
assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv));
string tname = des->local_symbol(path); string tname = des->local_symbol(path);
NetESignal*tmp = new NetESignal(tname, wid); NetESignal*tmp = new NetESignal(tname, wid);
tmp->set_line(*this); tmp->set_line(*this);
// Connect the pins from the lsb up to the msb.
unsigned off = net->sb_to_idx(lsv);
for (unsigned idx = 0 ; idx < wid ; idx += 1) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(tmp->pin(idx), net->pin(idx+lsv)); connect(tmp->pin(idx), net->pin(idx+off));
des->add_node(tmp); des->add_node(tmp);
return tmp; return tmp;
@ -1373,6 +1387,10 @@ NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix,
return am; return am;
} }
/*
* Elaborate an l-value as a NetNet (it may already exist) and make up
* the part select stuff for where the assignment is going to be made.
*/
NetNet* PAssign_::elaborate_lval(Design*des, const string&path, NetNet* PAssign_::elaborate_lval(Design*des, const string&path,
unsigned&msb, unsigned&lsb, unsigned&msb, unsigned&lsb,
NetExpr*&mux) const NetExpr*&mux) const
@ -1453,14 +1471,34 @@ NetNet* PAssign_::elaborate_lval(Design*des, const string&path,
} else { } else {
assert(id->msb_ == 0); assert(id->msb_ == 0);
assert(id->lsb_ == 0); assert(id->lsb_ == 0);
msb = reg->pin_count() - 1; msb = reg->msb();
lsb = 0; lsb = reg->lsb();
mux = 0; mux = 0;
} }
return reg; return reg;
} }
/*
* This funciton transforms an expression by padding the high bits
* with V0 until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide
* enough.
*/
static NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
{
if (wid > expr->expr_width()) {
verinum pad(verinum::V0, wid - expr->expr_width());
NetEConst*co = new NetEConst(pad);
NetEConcat*cc = new NetEConcat(2);
cc->set(0, co);
cc->set(1, expr);
cc->set_width(wid);
expr = cc;
}
return expr;
}
NetProc* PAssign::elaborate(Design*des, const string&path) const NetProc* PAssign::elaborate(Design*des, const string&path) const
{ {
/* Catch the case where the lvalue is a reference to a memory /* Catch the case where the lvalue is a reference to a memory
@ -1513,9 +1551,9 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
if (rise_time) { if (rise_time) {
string n = des->local_symbol(path); string n = des->local_symbol(path);
unsigned wid = msb - lsb + 1; unsigned wid = reg->pin_count();
if (! rv->set_width(wid)) { if (! rv->set_width(reg->pin_count())) {
cerr << get_line() << ": Unable to match expression " cerr << get_line() << ": Unable to match expression "
"width of " << rv->expr_width() << " to l-value" "width of " << rv->expr_width() << " to l-value"
" width of " << wid << "." << endl; " width of " << wid << "." << endl;
@ -1527,6 +1565,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
tmp->set_line(*this); tmp->set_line(*this);
des->add_signal(tmp); des->add_signal(tmp);
/* Generate an assignment of the l-value to the temporary... */
n = des->local_symbol(path); n = des->local_symbol(path);
NetAssign*a1 = new NetAssign(n, des, wid, rv); NetAssign*a1 = new NetAssign(n, des, wid, rv);
a1->set_line(*this); a1->set_line(*this);
@ -1535,6 +1574,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
for (unsigned idx = 0 ; idx < wid ; idx += 1) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(a1->pin(idx), tmp->pin(idx)); connect(a1->pin(idx), tmp->pin(idx));
/* Generate an assignment of the temporary to the r-value... */
n = des->local_symbol(path); n = des->local_symbol(path);
NetESignal*sig = new NetESignal(tmp); NetESignal*sig = new NetESignal(tmp);
des->add_node(sig); des->add_node(sig);
@ -1543,8 +1583,9 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
des->add_node(a2); des->add_node(a2);
for (unsigned idx = 0 ; idx < wid ; idx += 1) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(a2->pin(idx), reg->pin(idx+lsb)); connect(a2->pin(idx), reg->pin(idx));
/* And build up the complex statement. */
NetPDelay*de = new NetPDelay(rise_time, a2); NetPDelay*de = new NetPDelay(rise_time, a2);
NetBlock*bl = new NetBlock(NetBlock::SEQU); NetBlock*bl = new NetBlock(NetBlock::SEQU);
@ -1555,13 +1596,22 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
} }
if (mux == 0) { if (mux == 0) {
unsigned wid = msb - lsb + 1; /* This is a simple assign to a register. There may be a
part select, so take care that the width is of the
part, and using the lsb, make sure the correct range
of bits is assigned. */
unsigned wid = (msb >= lsb)? (msb-lsb+1) : (lsb-msb+1);
assert(wid <= reg->pin_count());
rv->set_width(wid); rv->set_width(wid);
rv = pad_to_width(rv, wid);
assert(rv->expr_width() >= wid);
cur = new NetAssign(des->local_symbol(path), des, wid, rv); cur = new NetAssign(des->local_symbol(path), des, wid, rv);
unsigned off = reg->sb_to_idx(lsb);
assert((off+wid) <= reg->pin_count());
for (unsigned idx = 0 ; idx < wid ; idx += 1) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(cur->pin(idx), reg->pin(idx+lsb)); connect(cur->pin(idx), reg->pin(idx+off));
} else { } else {
assert(reg->pin_count() == 1); assert(reg->pin_count() == 1);
@ -1611,18 +1661,9 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const
unsigned wid = msb - lsb + 1; unsigned wid = msb - lsb + 1;
rv->set_width(wid); rv->set_width(wid);
rv = pad_to_width(rv, wid);
assert(wid <= rv->expr_width());
/* If the l-value is larger then the r-value, then pad
the r-value with 0s. */
if (wid > rv->expr_width()) {
verinum pad(verinum::V0, wid-rv->expr_width());
NetEConst*co = new NetEConst(pad);
NetEConcat*cc = new NetEConcat(2);
cc->set(0, co);
cc->set(1, rv);
cc->set_width(wid);
rv = cc;
}
cur = new NetAssignNB(des->local_symbol(path), des, wid, rv); cur = new NetAssignNB(des->local_symbol(path), des, wid, rv);
for (unsigned idx = 0 ; idx < wid ; idx += 1) for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(cur->pin(idx), reg->pin(idx+lsb)); connect(cur->pin(idx), reg->pin(idx+lsb));
@ -2334,6 +2375,12 @@ Design* elaborate(const map<string,Module*>&modules,
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.83 1999/09/13 03:10:59 steve
* Clarify msb/lsb in context of netlist. Properly
* handle part selects in lval and rval of expressions,
* and document where the least significant bit goes
* in NetNet objects.
*
* Revision 1.82 1999/09/12 01:16:51 steve * Revision 1.82 1999/09/12 01:16:51 steve
* Pad r-values in certain assignments. * Pad r-values in certain assignments.
* *

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
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.60 1999/09/12 01:16:51 steve Exp $" #ident "$Id: netlist.cc,v 1.61 1999/09/13 03:10:59 steve Exp $"
#endif #endif
# include <cassert> # include <cassert>
@ -240,6 +240,18 @@ bool NetObj::has_compat_attributes(const NetObj&that) const
return true; return true;
} }
NetObj::Link& NetObj::pin(unsigned idx)
{
assert(idx < npins_);
return pins_[idx];
}
const NetObj::Link& NetObj::pin(unsigned idx) const
{
assert(idx < npins_);
return pins_[idx];
}
NetNode::~NetNode() NetNode::~NetNode()
{ {
if (design_) if (design_)
@ -272,6 +284,14 @@ NetNet::~NetNet()
design_->del_signal(this); design_->del_signal(this);
} }
unsigned NetNet::sb_to_idx(long sb) const
{
if (msb_ >= lsb_)
return sb - lsb_;
else
return lsb_ - sb;
}
NetProc::~NetProc() NetProc::~NetProc()
{ {
} }
@ -1762,6 +1782,12 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.61 1999/09/13 03:10:59 steve
* Clarify msb/lsb in context of netlist. Properly
* handle part selects in lval and rval of expressions,
* and document where the least significant bit goes
* in NetNet objects.
*
* Revision 1.60 1999/09/12 01:16:51 steve * Revision 1.60 1999/09/12 01:16:51 steve
* Pad r-values in certain assignments. * Pad r-values in certain assignments.
* *

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
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: netlist.h,v 1.62 1999/09/11 04:43:17 steve Exp $" #ident "$Id: netlist.h,v 1.63 1999/09/13 03:10:59 steve Exp $"
#endif #endif
/* /*
@ -170,8 +170,8 @@ class NetObj {
bool test_mark() const { return mark_; } bool test_mark() const { return mark_; }
void set_mark(bool flag=true) { mark_ = flag; } void set_mark(bool flag=true) { mark_ = flag; }
Link&pin(unsigned idx) { return pins_[idx]; } Link&pin(unsigned idx);
const Link&pin(unsigned idx) const { return pins_[idx]; } const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const; void dump_node_pins(ostream&, unsigned) const;
void dump_obj_attr(ostream&, unsigned) const; void dump_obj_attr(ostream&, unsigned) const;
@ -220,7 +220,8 @@ class NetNode : public NetObj {
* *
* Note that a net of any sort has exactly one pin. The pins feature * Note that a net of any sort has exactly one pin. The pins feature
* of the NetObj class is used to make a set of identical wires, in * of the NetObj class is used to make a set of identical wires, in
* order to support ranges, or busses. * order to support ranges, or busses. When dealing with vectors,
* pin(0) is always the least significant bit.
*/ */
class NetNet : public NetObj, public LineInfo { class NetNet : public NetObj, public LineInfo {
@ -243,15 +244,17 @@ class NetNet : public NetObj, public LineInfo {
PortType port_type() const { return port_type_; } PortType port_type() const { return port_type_; }
void port_type(PortType t) { port_type_ = t; } void port_type(PortType t) { port_type_ = t; }
/* These methods return the msb and lsb indices for the most
significant and least significant bits. These are signed
longs, and may be different from pin numbers. For example,
reg [1:8] has 8 bits, msb==1 and lsb==8. */
long msb() const { return msb_; } long msb() const { return msb_; }
long lsb() const { return lsb_; } long lsb() const { return lsb_; }
unsigned sb_to_idx(long sb) const /* This method converts a signed index (the type that might be
{ if (msb_ >= lsb_) found in the verilog source) to a pin number. It accounts
return sb - lsb_; for variation in the definition of the reg/wire/whatever. */
else unsigned sb_to_idx(long sb) const;
return lsb_ - sb;
}
bool local_flag() const { return local_flag_; } bool local_flag() const { return local_flag_; }
void local_flag(bool f) { local_flag_ = f; } void local_flag(bool f) { local_flag_ = f; }
@ -1556,6 +1559,12 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.63 1999/09/13 03:10:59 steve
* Clarify msb/lsb in context of netlist. Properly
* handle part selects in lval and rval of expressions,
* and document where the least significant bit goes
* in NetNet objects.
*
* Revision 1.62 1999/09/11 04:43:17 steve * Revision 1.62 1999/09/11 04:43:17 steve
* Support ternary and <= operators in vvm. * Support ternary and <= operators in vvm.
* *