Handle undefined L-value selects

L-value bit selects were incorrectly converting an undefined index to 0.

L-value part selects were asserting if an undefined index was given.

This patch unifies how all these are handle (including indexed part selects).

The base is set to an undefined value and an appropriate width is used.
A warning message is always printed since this is not a simple out of
range issue. It is the responsibility of the code generator to skip the
assignment, but we always want to execute the R-value since it could have
a side effect.
This commit is contained in:
Cary R 2013-01-25 10:25:12 -08:00
parent d9c400ac0c
commit 350369f3fc
1 changed files with 45 additions and 19 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -402,6 +402,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
ivl_assert(*this, index_tail.lsb == 0); ivl_assert(*this, index_tail.lsb == 0);
NetNet*reg = lv->sig(); NetNet*reg = lv->sig();
ivl_assert(*this, reg);
// Bit selects have a single select expression. Evaluate the // Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit // constant value and treat it as a part select with a bit
@ -410,10 +411,34 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
long lsb = 0; long lsb = 0;
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) { if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
lsb = index_con->value().as_long(); // The index has a constant defined value.
mux = 0; if (index_con->value().is_defined()) {
} lsb = index_con->value().as_long();
mux = 0;
// The index is undefined and this is a packed array.
} else if (prefix_indices.size()+2 <= reg->packed_dims().size()) {
long loff;
unsigned long lwid;
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, rcl);
cerr << get_fileline() << ": warning: L-value packed array "
<< "select of " << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
return true;
// The index is undefined and this is a bit select.
} else {
cerr << get_fileline() << ": warning: L-value bit select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
return true;
}
}
if (prefix_indices.size()+2 <= reg->packed_dims().size()) { if (prefix_indices.size()+2 <= reg->packed_dims().size()) {
// Special case: this is a slice of a multi-dimensional // Special case: this is a slice of a multi-dimensional
@ -516,14 +541,22 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
long msb, lsb; long msb, lsb;
bool parts_defined_flag; bool parts_defined_flag;
bool flag = calculate_parts_(des, scope, msb, lsb, parts_defined_flag); bool flag = calculate_parts_(des, scope, msb, lsb, parts_defined_flag);
if (!flag) if (!flag) return false;
return false;
ivl_assert(*this, parts_defined_flag);
NetNet*reg = lv->sig(); NetNet*reg = lv->sig();
ivl_assert(*this, reg); ivl_assert(*this, reg);
if (! parts_defined_flag) {
cerr << get_fileline() << ": warning: L-value part select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
// Use a width of two here so we can distinguish between an
// undefined bit or part select.
lv->set_part(new NetEConst(verinum(verinum::Vx)), 2);
return true;
}
const vector<netrange_t>&packed = reg->packed_dims(); const vector<netrange_t>&packed = reg->packed_dims();
// Part selects cannot select slices. So there must be enough // Part selects cannot select slices. So there must be enough
@ -654,17 +687,10 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
} }
} }
} else { } else {
if (warn_ob_select) { cerr << get_fileline() << ": warning: L-value indexed part "
cerr << get_fileline() << ": warning: " << reg->name(); << "select of " << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]"; if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "['bx"; cerr << " has an undefined base." << endl;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is always outside vector." << endl;
}
} }
} else { } else {
ivl_assert(*this, prefix_indices.size()+1 == reg->packed_dims().size()); ivl_assert(*this, prefix_indices.size()+1 == reg->packed_dims().size());