diff --git a/elab_net.cc b/elab_net.cc index 3cee67cec..1a2161deb 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -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.179 2006/04/10 00:32:14 steve Exp $" +#ident "$Id: elab_net.cc,v 1.180 2006/04/24 05:15:07 steve Exp $" #endif # include "config.h" @@ -1884,69 +1884,138 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const 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); + switch (sel_) { + default: + cerr << get_line() << ": internal error: " + << "Unexpected sel_ value = " << sel_ << endl; + assert(0); + break; - midx = sig->sb_to_idx(mval->as_long()); - lidx = sig->sb_to_idx(lval->as_long()); + case PEIdent::SEL_IDX_DO: + case PEIdent::SEL_IDX_UP: { + assert(msb_); + assert(lsb_); + assert(idx_.empty()); - /* 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; - } + NetExpr*tmp_ex = elab_and_eval(des, scope, msb_); + NetEConst*tmp = dynamic_cast(tmp_ex); + assert(tmp); - /* 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; + long midx_val = tmp->value().as_long(); + midx = sig->sb_to_idx(midx_val); + delete tmp_ex; + + tmp_ex = elab_and_eval(des, scope, lsb_); + tmp = dynamic_cast(tmp_ex); + assert(tmp); + + long wid = tmp->value().as_long(); + delete tmp_ex; + + if (sel_ == PEIdent::SEL_IDX_UP) + lidx = sig->sb_to_idx(midx_val+wid-1); + else + lidx = sig->sb_to_idx(midx_val-wid+1); + + if (midx < lidx) { + long tmp = midx; + midx = lidx; + lidx = tmp; + } + + break; + } + + case PEIdent::SEL_PART: { + assert(msb_); + assert(lsb_); + assert(idx_.empty()); + + NetExpr*tmp_ex = elab_and_eval(des, scope, msb_); + NetEConst*tmp = dynamic_cast(tmp_ex); + assert(tmp); + + long midx_val = tmp->value().as_long(); + midx = sig->sb_to_idx(midx_val); + delete tmp_ex; + + tmp_ex = elab_and_eval(des, scope, lsb_); + tmp = dynamic_cast(tmp_ex); + assert(tmp); + + long lidx_val = tmp->value().as_long(); + lidx = sig->sb_to_idx(lidx_val); + delete tmp_ex; + + /* Detect reversed indices of a part select. */ + if (lidx > midx) { + cerr << get_line() << ": error: Part select " + << sig->name() << "[" << midx_val << ":" + << lidx_val << "] indices reversed." << endl; + cerr << get_line() << ": : Did you mean " + << sig->name() << "[" << lidx_val << ":" + << midx_val << "]?" << 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() << "[" << midx_val << ":" + << midx_val << "] out of range." << endl; + midx = sig->vector_width() - 1; + lidx = 0; + des->errors += 1; + } + break; + } + + case PEIdent::SEL_NONE: + if (!idx_.empty()) { + assert(msb_ == 0); + assert(lsb_ == 0); + assert(idx_.size() == 1); + verinum*mval = idx_[0]->eval_const(des, scope); + if (mval == 0) { + cerr << get_line() << ": error: Index of " << path_ << + " needs to be constant in this context." << + endl; + cerr << get_line() << ": : Index expression is: " + << *(idx_[0]) << 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 { + if (msb_ || lsb_) { + cerr << get_line() << ": internal error: " + << "Unexpected msb_/lsb_ values?" << endl; + if (msb_) + cerr << get_line() << " : " + << *msb_ << endl; + if (lsb_) + cerr << get_line() << " : " + << *lsb_ << endl; + } + assert(msb_ == 0 && lsb_ == 0); midx = sig->vector_width() - 1; lidx = 0; - des->errors += 1; } - - } else if (!idx_.empty()) { - assert(msb_ == 0); - assert(lsb_ == 0); - assert(idx_.size() == 1); - verinum*mval = idx_[0]->eval_const(des, scope); - if (mval == 0) { - cerr << get_line() << ": error: Index of " << path_ << - " needs to be constant in this context." << - endl; - cerr << get_line() << ": : Index expression is: " - << *(idx_[0]) << 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; + break; } return true; @@ -2662,6 +2731,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.180 2006/04/24 05:15:07 steve + * Fix support for indexed part select in continuous assign l-values. + * * Revision 1.179 2006/04/10 00:32:14 steve * Clean up index expression error message. * diff --git a/parse.y b/parse.y index 152770bda..0a708f103 100644 --- a/parse.y +++ b/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.215 2006/04/17 04:35:49 steve Exp $" +#ident "$Id: parse.y,v 1.216 2006/04/24 05:15:07 steve Exp $" #endif # include "config.h" @@ -1287,6 +1287,7 @@ indexed_identifier } | indexed_identifier '[' expression ']' { PEIdent*tmp = $1; + tmp->sel_ = PEIdent::SEL_NONE; tmp->idx_.push_back($3); $$ = tmp; } @@ -2224,6 +2225,7 @@ port_reference } wtmp->msb_ = $3; wtmp->lsb_ = $5; + wtmp->sel_ = PEIdent::SEL_PART; Module::port_t*ptmp = new Module::port_t; ptmp->name = perm_string(); ptmp->expr = svector(1);