V0.9: 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:26:26 -08:00
parent 4b805a2b89
commit edf741106d
1 changed files with 31 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -336,6 +336,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
ivl_assert(*this, index_tail.lsb == 0);
NetNet*reg = lv->sig();
assert(reg);
// These are not used, but they need to have a default value.
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
@ -350,8 +351,20 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
long lsb = 0;
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
lsb = index_con->value().as_long();
mux = 0;
// The index has a constant defined value.
if (index_con->value().is_defined()) {
lsb = index_con->value().as_long();
mux = 0;
// The index is undefined.
} else {
cerr << get_fileline() << ": warning: L-value bit select of "
<< reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
return true;
}
}
if (mux) {
@ -393,14 +406,21 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
long msb, lsb;
bool parts_defined_flag;
bool flag = calculate_parts_(des, scope, msb, lsb, parts_defined_flag);
if (!flag)
return false;
ivl_assert(*this, parts_defined_flag);
if (!flag) return false;
NetNet*reg = lv->sig();
assert(reg);
if (! parts_defined_flag) {
cerr << get_fileline() << ": warning: L-value part select of "
<< reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
return true;
}
if (msb == reg->msb() && lsb == reg->lsb()) {
/* Part select covers the entire vector. Simplest case. */
@ -517,17 +537,10 @@ 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 << "[]";
cerr << "['bx";
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is always outside vector." << endl;
}
cerr << get_fileline() << ": warning: L-value indexed part "
<< "select of " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << " has an undefined base." << endl;
}
} else {
/* Correct the mux for the range of the vector. */