Permalink
Browse files

Get unpacked arrays working.

  • Loading branch information...
1 parent f7ba954 commit 6e8aef82626d174aba7e53666652cb5087e780b2 @steveicarus committed May 25, 2012
Showing with 467 additions and 316 deletions.
  1. +4 −5 PWire.cc
  2. +3 −4 PWire.h
  3. +10 −1 design_dump.cc
  4. +49 −58 elab_expr.cc
  5. +46 −37 elab_lval.cc
  6. +43 −38 elab_net.cc
  7. +20 −25 elab_sig.cc
  8. +1 −1 net_nex_input.cc
  9. +27 −58 netlist.cc
  10. +8 −13 netlist.h
  11. +192 −41 netmisc.cc
  12. +31 −2 netmisc.h
  13. +2 −20 parse.y
  14. +3 −2 pform.cc
  15. +2 −1 pform.h
  16. +5 −4 pform_dump.cc
  17. +19 −4 t-dll.cc
  18. +2 −2 t-dll.h
View
@@ -29,7 +29,7 @@ PWire::PWire(perm_string n,
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_set_(false), net_set_(false), is_scalar_(false),
- error_cnt_(0), lidx_(0), ridx_(0), enum_type_(0), struct_type_(0),
+ error_cnt_(0), enum_type_(0), struct_type_(0),
discipline_(0)
{
if (t == NetNet::INTEGER) {
@@ -242,15 +242,14 @@ void PWire::set_range(const list<pform_range_t>&rlist, PWSRType type)
}
}
-void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
+void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
{
- if (lidx_ != 0 || ridx_ != 0) {
+ if (! unpacked_.empty()) {
cerr << get_fileline() << ": error: Array ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
- lidx_ = ldx;
- ridx_ = rdx;
+ unpacked_ = ranges;
}
}
View
@@ -78,7 +78,7 @@ class PWire : public LineInfo {
void set_range_scalar(PWSRType type);
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
- void set_memory_idx(PExpr*ldx, PExpr*rdx);
+ void set_unpacked_idx(const std::list<pform_range_t>&ranges);
void set_enumeration(enum_type_t*enum_type);
void set_struct_type(struct_type_t*type);
@@ -115,9 +115,8 @@ class PWire : public LineInfo {
unsigned error_cnt_;
// If this wire is actually a memory, these indices will give
- // me the size and address range of the memory.
- PExpr*lidx_;
- PExpr*ridx_;
+ // me the size and address ranges of the memory.
+ std::list<pform_range_t>unpacked_;
enum_type_t*enum_type_;
struct_type_t*struct_type_;
View
@@ -196,11 +196,20 @@ ostream&operator<<(ostream&out, const list<NetNet::range_t>&rlist)
return out;
}
+ostream&operator<<(ostream&out, const vector<NetNet::range_t>&rlist)
+{
+ for (vector<NetNet::range_t>::const_iterator cur = rlist.begin()
+ ; cur != rlist.end() ; ++cur) {
+ out << "[" << cur->msb << ":" << cur->lsb << "]";
+ }
+ return out;
+}
+
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name()
- << "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
+ << unpacked_dims_ << " unpacked dims=" << unpacked_dimensions() << " count=" << pin_count();
if (local_flag_)
o << " (local)";
o << " " << data_type_;
View
@@ -1873,7 +1873,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
{
list<index_component_t> index;
index = path_.back().index;
- for (size_t idx = 0 ; idx < net->array_dimensions() ; idx += 1)
+ for (size_t idx = 0 ; idx < net->unpacked_dimensions() ; idx += 1)
index.pop_front();
return evaluate_index_prefix(des, scope, prefix_indices, index);
@@ -2073,7 +2073,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
if (!name_tail.index.empty()) {
const index_component_t&index_tail = name_tail.index.back();
// Skip full array word net selects.
- if (!net || (name_tail.index.size() > net->array_dimensions())) {
+ if (!net || (name_tail.index.size() > net->unpacked_dimensions())) {
use_sel = index_tail.sel;
}
}
@@ -3037,78 +3037,69 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
const name_component_t&name_tail = path_.back();
- if (name_tail.index.empty() && !(SYS_TASK_ARG & flags)) {
+ // Special case: This is the entire array, and we are a direct
+ // argument of a system task.
+ if (name_tail.index.empty() && (SYS_TASK_ARG & flags)) {
+ NetESignal*res = new NetESignal(net, 0);
+ res->set_line(*this);
+ return res;
+ }
+
+ if (name_tail.index.empty()) {
cerr << get_fileline() << ": error: Array " << path()
<< " Needs an array index here." << endl;
des->errors += 1;
return 0;
}
- index_component_t index_front;
- if (! name_tail.index.empty()) {
- index_front = name_tail.index.front();
- ivl_assert(*this, index_front.sel != index_component_t::SEL_NONE);
- if (index_front.sel != index_component_t::SEL_BIT) {
- cerr << get_fileline() << ": error: Array " << path_
- << " cannot be indexed by a range." << endl;
- des->errors += 1;
- return 0;
- }
- ivl_assert(*this, index_front.msb);
- ivl_assert(*this, !index_front.lsb);
- }
-
- NetExpr*word_index = 0;
- if (index_front.sel != index_component_t::SEL_NONE)
- word_index = elab_and_eval(des, scope, index_front.msb, -1,
- need_const);
-
- if (word_index == 0 && !(SYS_TASK_ARG & flags))
+ // Make sure there are enough indices to address an array element.
+ if (name_tail.index.size() < net->unpacked_dimensions()) {
+ cerr << get_fileline() << ": error: Array " << path()
+ << " needs " << net->unpacked_dimensions() << " indices,"
+ << " but got only " << name_tail.index.size() << "." << endl;
+ des->errors += 1;
return 0;
+ }
- if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) {
- long addr = word_addr->value().as_long();
-
- // Special case: The index is out of range, so the value
- // of this expression is a 'bx vector the width of a word.
- if (!net->array_index_is_valid(addr)) {
- cerr << get_fileline() << ": warning: returning 'bx for out "
- "of bounds array access " << net->name()
- << "[" << addr << "]." << endl;
- NetEConst*resx = make_const_x(net->vector_width());
- resx->set_line(*this);
- delete word_index;
- return resx;
- }
-
- // Recalculate the constant address with the adjusted base.
- unsigned use_addr = net->array_index_to_address(addr);
- if (addr < 0 || use_addr != (unsigned long)addr) {
- verinum val ( (uint64_t)use_addr, 8*sizeof(use_addr));
- NetEConst*tmp = new NetEConst(val);
- tmp->set_line(*this);
- delete word_index;
- word_index = tmp;
+ // Evaluate all the index expressions into an
+ // "unpacked_indices" array.
+ list<NetExpr*>unpacked_indices;
+ list<long> unpacked_indices_const;
+ bool flag = indices_to_expressions(des, scope, this,
+ name_tail.index, net->unpacked_dimensions(),
+ need_const,
+ unpacked_indices,
+ unpacked_indices_const);
+
+ NetExpr*canon_index = 0;
+ if (flag) {
+ ivl_assert(*this, unpacked_indices_const.size() == net->unpacked_dimensions());
+ canon_index = normalize_variable_unpacked(net, unpacked_indices_const);
+
+ if (canon_index == 0) {
+ cerr << get_fileline() << ": warning: "
+ << "returning 'bx for out of bounds array access "
+ << net->name() << as_indices(unpacked_indices_const) << "." << endl;
}
- } else if (word_index) {
- // If there is a non-zero base to the memory, then build an
- // expression to calculate the canonical address.
- if (long base = net->array_first()) {
+ } else {
+ ivl_assert(*this, unpacked_indices.size() == net->unpacked_dimensions());
+ canon_index = normalize_variable_unpacked(net, unpacked_indices);
+ }
- word_index = normalize_variable_array_base(
- word_index, base, net->array_count());
- eval_expr(word_index);
- }
+ if (canon_index == 0) {
+ NetEConst*xxx = make_const_x(net->vector_width());
+ xxx->set_line(*this);
+ return xxx;
}
- NetESignal*res = new NetESignal(net, word_index);
+ NetESignal*res = new NetESignal(net, canon_index);
res->set_line(*this);
// Detect that the word has a bit/part select as well.
index_component_t::ctype_t word_sel = index_component_t::SEL_NONE;
- if (name_tail.index.size() > 1)
+ if (name_tail.index.size() > net->unpacked_dimensions())
word_sel = name_tail.index.back().sel;
if (net->get_scalar() &&
@@ -3117,7 +3108,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
if (res->expr_type() == IVL_VT_REAL) cerr << "real";
else cerr << "scalar";
cerr << " array word: " << net->name()
- <<"[" << *word_index << "]" << endl;
+ << as_indices(unpacked_indices) << endl;
des->errors += 1;
delete res;
return 0;
@@ -3599,7 +3590,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const
{
- if (net->array_dimensions() > 0)
+ if (net->unpacked_dimensions() > 0)
return elaborate_expr_net_word_(des, scope, net, found_in,
expr_wid, flags);
View
@@ -202,7 +202,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
// slice. This is, in fact, an error in l-values. Detect the
// situation by noting if the index count is less than the
// array dimensions (unpacked).
- if (reg->array_dimensions() > name_tail.index.size()) {
+ if (reg->unpacked_dimensions() > name_tail.index.size()) {
cerr << get_fileline() << ": error: Cannot assign to array "
<< path_ << ". Did you forget a word index?" << endl;
des->errors += 1;
@@ -228,7 +228,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return lv;
}
- if (reg->array_dimensions() > 0)
+ if (reg->unpacked_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
// This must be after the array word elaboration above!
@@ -278,6 +278,15 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
+ if (name_tail.index.size() < reg->unpacked_dimensions()) {
+ cerr << get_fileline() << ": error: Array " << reg->name()
+ << " needs " << reg->unpacked_dimensions() << " indices,"
+ << " but got only " << name_tail.index.size() << "." << endl;
+ des->errors += 1;
+ return 0;
+ }
+
+ // Make sure there are enough indices to address an array element.
const index_component_t&index_head = name_tail.index.front();
if (index_head.sel == index_component_t::SEL_PART) {
cerr << get_fileline() << ": error: cannot perform a part "
@@ -286,47 +295,47 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
return 0;
}
- ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
- ivl_assert(*this, index_head.msb != 0);
- ivl_assert(*this, index_head.lsb == 0);
- NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
-
- // If there is a non-zero base to the memory, then build an
- // expression to calculate the canonical address.
- if (long base = reg->array_first()) {
-
- word = normalize_variable_array_base(word, base,
- reg->array_count());
- eval_expr(word);
+ // Evaluate all the index expressions into an
+ // "unpacked_indices" array.
+ list<NetExpr*>unpacked_indices;
+ list<long> unpacked_indices_const;
+ bool flag = indices_to_expressions(des, scope, this,
+ name_tail.index, reg->unpacked_dimensions(),
+ false,
+ unpacked_indices,
+ unpacked_indices_const);
+
+ NetExpr*canon_index = 0;
+ if (flag) {
+ ivl_assert(*this, unpacked_indices_const.size() == reg->unpacked_dimensions());
+ canon_index = normalize_variable_unpacked(reg, unpacked_indices_const);
+ if (canon_index == 0) {
+ cerr << get_fileline() << ": warning: "
+ << "ignoring out of bounds l-value array access " << reg->name();
+ for (list<long>::const_iterator cur = unpacked_indices_const.begin()
+ ; cur != unpacked_indices_const.end() ; ++cur) {
+ cerr << "[" << *cur << "]";
+ }
+ cerr << "." << endl;
+ }
+ } else {
+ ivl_assert(*this, unpacked_indices.size() == reg->unpacked_dimensions());
+ canon_index = normalize_variable_unpacked(reg, unpacked_indices);
}
+
NetAssign_*lv = new NetAssign_(reg);
- lv->set_word(word);
+ lv->set_word(canon_index);
if (debug_elaborate)
- cerr << get_fileline() << ": debug: Set array word=" << *word << endl;
-
- // Test for the case that the index is a constant, and is out
- // of bounds. The "word" expression is the word index already
- // converted to canonical address, so this just needs to check
- // that the address is not too big.
- if (NetEConst*word_const = dynamic_cast<NetEConst*>(word)) {
- verinum word_val = word_const->value();
- long index = word_val.as_long();
-
- if (index < 0 || index >= (long) reg->array_count()) {
- cerr << get_fileline() << ": warning: Constant array index "
- << (index + reg->array_first())
- << " is out of range for array "
- << reg->name() << "." << endl;
- }
- }
+ cerr << get_fileline() << ": debug: Set array word=" << *canon_index << endl;
+
/* An array word may also have part selects applied to them. */
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
- if (name_tail.index.size() > 1)
+ if (name_tail.index.size() > reg->unpacked_dimensions())
use_sel = name_tail.index.back().sel;
if (reg->get_scalar() &&
@@ -335,7 +344,7 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
if (reg->data_type() == IVL_VT_REAL) cerr << "real";
else cerr << "scalar";
cerr << " array word: " << reg->name()
- << "[" << *word << "]" << endl;
+ << "[" << *canon_index << "]" << endl;
des->errors += 1;
return 0;
}
@@ -563,7 +572,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
if (warn_ob_select) {
if (rel_base < 0) {
cerr << get_fileline() << ": warning: " << reg->name();
- if (reg->array_dimensions() > 0) cerr << "[]";
+ if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
@@ -574,7 +583,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
}
if (rel_base + wid > reg->vector_width()) {
cerr << get_fileline() << ": warning: " << reg->name();
- if (reg->array_dimensions() > 0) cerr << "[]";
+ if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
@@ -587,7 +596,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
} else {
if (warn_ob_select) {
cerr << get_fileline() << ": warning: " << reg->name();
- if (reg->array_dimensions() > 0) cerr << "[]";
+ if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "['bx";
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
Oops, something went wrong.

0 comments on commit 6e8aef8

Please sign in to comment.