Skip to content

Commit

Permalink
Merge branch 'pei1'
Browse files Browse the repository at this point in the history
  • Loading branch information
steveicarus committed May 25, 2012
2 parents ceaa60d + 6e8aef8 commit 3426462
Show file tree
Hide file tree
Showing 18 changed files with 466 additions and 315 deletions.
9 changes: 4 additions & 5 deletions PWire.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}

Expand Down
7 changes: 3 additions & 4 deletions PWire.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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_;
Expand Down
11 changes: 10 additions & 1 deletion design_dump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,20 @@ ostream&operator<<(ostream&out, const list<netrange_t>&rlist)
return out;
}

ostream&operator<<(ostream&out, const vector<netrange_t>&rlist)
{
for (vector<netrange_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_;
Expand Down
103 changes: 47 additions & 56 deletions elab_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1974,7 +1974,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);
Expand Down Expand Up @@ -2174,7 +2174,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;
}
}
Expand Down Expand Up @@ -3146,78 +3146,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);
// 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;
}

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);
// 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);

if (word_index == 0 && !(SYS_TASK_ARG & flags))
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;
}
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);

// 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;
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() &&
Expand All @@ -3226,7 +3217,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;
Expand Down Expand Up @@ -3708,7 +3699,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);

Expand Down
83 changes: 46 additions & 37 deletions elab_lval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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!
Expand Down Expand Up @@ -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 "
Expand All @@ -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() &&
Expand All @@ -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;
}
Expand Down Expand Up @@ -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 << "+:";
Expand All @@ -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 << "+:";
Expand All @@ -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 << "+:";
Expand Down
Loading

0 comments on commit 3426462

Please sign in to comment.