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:
parent
6847dac5c2
commit
7a211b9136
93
elaborate.cc
93
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -105,11 +105,17 @@ void PWire::elaborate(Design*des, const string&path) const
|
|||
wtype = NetNet::REG;
|
||||
|
||||
unsigned wid = 1;
|
||||
long lsb = 0, msb = 0;
|
||||
|
||||
if (msb_.count()) {
|
||||
svector<long>mnum (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) {
|
||||
verinum*mval = msb_[idx]->eval_const(des,path);
|
||||
if (mval == 0) {
|
||||
|
|
@ -134,6 +140,8 @@ void PWire::elaborate(Design*des, const string&path) const
|
|||
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) {
|
||||
if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) {
|
||||
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])
|
||||
wid = mnum[0] - lnum[0] + 1;
|
||||
else
|
||||
|
|
@ -173,7 +183,7 @@ void PWire::elaborate(Design*des, const string&path) const
|
|||
|
||||
} else {
|
||||
|
||||
NetNet*sig = new NetNet(path + "." + name_, wtype, wid);
|
||||
NetNet*sig = new NetNet(path + "." + name_, wtype, msb, lsb);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
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);
|
||||
unsigned long lsv = lsn->as_ulong();
|
||||
unsigned long msv = msn->as_ulong();
|
||||
assert(msv >= lsv);
|
||||
unsigned long wid = msv-lsv+1;
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
assert(wid <= net->pin_count());
|
||||
assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv));
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetESignal*tmp = new NetESignal(tname, wid);
|
||||
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)
|
||||
connect(tmp->pin(idx), net->pin(idx+lsv));
|
||||
connect(tmp->pin(idx), net->pin(idx+off));
|
||||
|
||||
des->add_node(tmp);
|
||||
return tmp;
|
||||
|
|
@ -1373,6 +1387,10 @@ NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix,
|
|||
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,
|
||||
unsigned&msb, unsigned&lsb,
|
||||
NetExpr*&mux) const
|
||||
|
|
@ -1453,14 +1471,34 @@ NetNet* PAssign_::elaborate_lval(Design*des, const string&path,
|
|||
} else {
|
||||
assert(id->msb_ == 0);
|
||||
assert(id->lsb_ == 0);
|
||||
msb = reg->pin_count() - 1;
|
||||
lsb = 0;
|
||||
msb = reg->msb();
|
||||
lsb = reg->lsb();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
/* 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) {
|
||||
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 "
|
||||
"width of " << rv->expr_width() << " to l-value"
|
||||
" width of " << wid << "." << endl;
|
||||
|
|
@ -1527,6 +1565,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
|
|||
tmp->set_line(*this);
|
||||
des->add_signal(tmp);
|
||||
|
||||
/* Generate an assignment of the l-value to the temporary... */
|
||||
n = des->local_symbol(path);
|
||||
NetAssign*a1 = new NetAssign(n, des, wid, rv);
|
||||
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)
|
||||
connect(a1->pin(idx), tmp->pin(idx));
|
||||
|
||||
/* Generate an assignment of the temporary to the r-value... */
|
||||
n = des->local_symbol(path);
|
||||
NetESignal*sig = new NetESignal(tmp);
|
||||
des->add_node(sig);
|
||||
|
|
@ -1543,8 +1583,9 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
|
|||
des->add_node(a2);
|
||||
|
||||
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);
|
||||
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU);
|
||||
|
|
@ -1555,13 +1596,22 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
|
|||
}
|
||||
|
||||
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 = pad_to_width(rv, wid);
|
||||
assert(rv->expr_width() >= wid);
|
||||
|
||||
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)
|
||||
connect(cur->pin(idx), reg->pin(idx+lsb));
|
||||
connect(cur->pin(idx), reg->pin(idx+off));
|
||||
|
||||
} else {
|
||||
assert(reg->pin_count() == 1);
|
||||
|
|
@ -1611,18 +1661,9 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const
|
|||
unsigned wid = msb - lsb + 1;
|
||||
|
||||
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);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(cur->pin(idx), reg->pin(idx+lsb));
|
||||
|
|
@ -2334,6 +2375,12 @@ Design* elaborate(const map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Pad r-values in certain assignments.
|
||||
*
|
||||
|
|
|
|||
28
netlist.cc
28
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -240,6 +240,18 @@ bool NetObj::has_compat_attributes(const NetObj&that) const
|
|||
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()
|
||||
{
|
||||
if (design_)
|
||||
|
|
@ -272,6 +284,14 @@ NetNet::~NetNet()
|
|||
design_->del_signal(this);
|
||||
}
|
||||
|
||||
unsigned NetNet::sb_to_idx(long sb) const
|
||||
{
|
||||
if (msb_ >= lsb_)
|
||||
return sb - lsb_;
|
||||
else
|
||||
return lsb_ - sb;
|
||||
}
|
||||
|
||||
NetProc::~NetProc()
|
||||
{
|
||||
}
|
||||
|
|
@ -1762,6 +1782,12 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Pad r-values in certain assignments.
|
||||
*
|
||||
|
|
|
|||
29
netlist.h
29
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -170,8 +170,8 @@ class NetObj {
|
|||
bool test_mark() const { return mark_; }
|
||||
void set_mark(bool flag=true) { mark_ = flag; }
|
||||
|
||||
Link&pin(unsigned idx) { return pins_[idx]; }
|
||||
const Link&pin(unsigned idx) const { return pins_[idx]; }
|
||||
Link&pin(unsigned idx);
|
||||
const Link&pin(unsigned idx) const;
|
||||
|
||||
void dump_node_pins(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
|
||||
* 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 {
|
||||
|
||||
|
|
@ -243,15 +244,17 @@ class NetNet : public NetObj, public LineInfo {
|
|||
PortType port_type() const { return port_type_; }
|
||||
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 lsb() const { return lsb_; }
|
||||
|
||||
unsigned sb_to_idx(long sb) const
|
||||
{ if (msb_ >= lsb_)
|
||||
return sb - lsb_;
|
||||
else
|
||||
return lsb_ - sb;
|
||||
}
|
||||
/* This method converts a signed index (the type that might be
|
||||
found in the verilog source) to a pin number. It accounts
|
||||
for variation in the definition of the reg/wire/whatever. */
|
||||
unsigned sb_to_idx(long sb) const;
|
||||
|
||||
bool local_flag() const { return local_flag_; }
|
||||
void local_flag(bool f) { local_flag_ = f; }
|
||||
|
|
@ -1556,6 +1559,12 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Support ternary and <= operators in vvm.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue