Don't make useless arrays of nexa

When a pin array is virtual, dll_target::signal() doesn't need
to make a corresponding set of stub nexa.

This patch includes new detection of oversized arrays, configurable
with the ARRAY_SIZE_LIMIT flag.  This limit only applies to devirtualized
arrays; virtual arrays are only limited by your architecture's
unsigned int type.

The concept and earlier versions of this patch have been successfully
stress-tested by multiple people.  This one causes no testsuite
regressions on my machine.

Closes: pr2023076
(cherry picked from commit 3a18bda8ee)
This commit is contained in:
Larry Doolittle 2009-03-11 09:18:30 -07:00 committed by Stephen Williams
parent 9473e823ed
commit 0e8a12eebf
7 changed files with 54 additions and 15 deletions

View File

@ -92,6 +92,9 @@ extern bool debug_optimizer;
/* Possibly temporary flag to control virtualization of pin arrays */
extern bool disable_virtual_pins;
/* Limit to size of devirtualized arrays */
extern unsigned long array_size_limit;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;

View File

@ -843,8 +843,8 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
/*
* Elaborate a source wire. The "wire" is the declaration of wires,
* registers, ports and memories. The parser has already merged the
* multiple properties of a wire (i.e., "input wire") so come the
* elaboration this creates an object in the design that represent the
* multiple properties of a wire (i.e., "input wire"), so come the
* elaboration this creates an object in the design that represents the
* defined item.
*/
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
@ -1108,6 +1108,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
: new NetNet(scope, name_, wtype, msb, lsb);
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;

View File

@ -131,7 +131,8 @@ bool debug_optimizer = false;
/*
* Miscellaneous flags.
*/
bool disable_virtual_pins = false; // XXX needs a way for user to set
bool disable_virtual_pins = false;
unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364?
/*
* Verbose messages enabled.
@ -714,8 +715,10 @@ int main(int argc, char*argv[])
cout << endl << "PARSING INPUT" << endl;
}
const char *flag_dvp = flags["DISABLE_VIRTUAL_PINS"];
if (flag_dvp) disable_virtual_pins = strcmp(flag_dvp,"true")==0;
const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0;
flag_tmp = flags["ARRAY_SIZE_LIMIT"];
if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0);
/* Parse the input. Make the pform. */
int rc = pform_parse(argv[optind]);

View File

@ -175,6 +175,12 @@ Link* find_next_output(Link*lnk)
void NetPins::devirtualize_pins(void)
{
if (pins_) return;
if (npins_ > array_size_limit) {
cerr << get_fileline() << ": error: pin count " << npins_ <<
" exceeds " << array_size_limit <<
" (set by -pARRAY_SIZE_LIMIT)" << endl;
assert(0);
}
if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
pins_ = new Link[npins_];
@ -263,6 +269,11 @@ bool NetPins::is_linked(void)
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
{
/* Don't
ivl_assert(*this, np > 0);
* because it would happen before we get to print a useful
* message in the NetNet constructor
*/
}
NetObj::~NetObj()
@ -568,12 +579,14 @@ static unsigned calculate_count(long s, long e)
{
unsigned long r;
if (s >= e) {
r = s - e + 1;
r = s - e;
} else {
r = e - s + 1;
r = e - s;
}
assert (r <= UINT_MAX);
return r;
if (r >= UINT_MAX) {
return 0;
}
return r + 1;
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
@ -584,7 +597,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
ivl_assert(*this, s);
if (pin_count() == 0) {
cerr << "Array too big [" << array_s << ":" << array_e << "]" << endl;
ivl_assert(*this, 0);
}
verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE;
@ -778,7 +795,9 @@ bool NetNet::array_addr_swapped() const
unsigned NetNet::array_count() const
{
return calculate_count(s0_, e0_);
unsigned c = calculate_count(s0_, e0_);
ivl_assert(*this, c > 0);
return c;
}
bool NetNet::array_index_is_valid(long sb) const

View File

@ -197,10 +197,10 @@ class NetPins : public LineInfo {
void set_default_init(verinum::V val);
bool is_linked();
bool pins_are_virtual(void) const;
void devirtualize_pins(void);
private:
Link*pins_;
void devirtualize_pins(void);
const unsigned npins_;
Link::DIR default_dir_;
verinum::V default_init_;

View File

@ -1893,10 +1893,16 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
{
assert(word < net->array_words);
if (net->array_words > 1)
return net->pins[word];
else
if (net->array_words > 1) {
if (net->pins) {
return net->pins[word];
} else {
cerr << "AACK! ivl_signal_nex() returning NULL" << endl;
return NULL;
}
} else {
return net->pin;
}
}
extern "C" int ivl_signal_msb(ivl_signal_t net)

View File

@ -2564,6 +2564,12 @@ void dll_target::signal(const NetNet*net)
assert(obj->array_words == net->pin_count());
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
"t-dll creating nexus array " << obj->array_words << " long" << endl;
if (obj->array_words > 1 && net->pins_are_virtual()) {
obj->pins = NULL;
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
"t-dll used NULL for big nexus array" << endl;
return;
}
if (obj->array_words > 1)
obj->pins = new ivl_nexus_t[obj->array_words];