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
This commit is contained in:
Larry Doolittle 2009-03-11 09:18:30 -07:00 committed by Stephen Williams
parent 932aa49b38
commit 3a18bda8ee
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 */ /* Possibly temporary flag to control virtualization of pin arrays */
extern bool disable_virtual_pins; 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. */ /* Path to a directory useful for finding subcomponents. */
extern const char*basedir; 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, * Elaborate a source wire. The "wire" is the declaration of wires,
* registers, ports and memories. The parser has already merged the * registers, ports and memories. The parser has already merged the
* multiple properties of a wire (i.e., "input wire") so come the * multiple properties of a wire (i.e., "input wire"), so come the
* elaboration this creates an object in the design that represent the * elaboration this creates an object in the design that represents the
* defined item. * defined item.
*/ */
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const 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, array_s0, array_e0)
: new NetNet(scope, name_, wtype, msb, lsb); : new NetNet(scope, name_, wtype, msb, lsb);
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
ivl_variable_type_t use_data_type = data_type_; ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) { if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC; use_data_type = IVL_VT_LOGIC;

View File

@ -131,7 +131,8 @@ bool debug_optimizer = false;
/* /*
* Miscellaneous flags. * 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. * Verbose messages enabled.
@ -714,8 +715,10 @@ int main(int argc, char*argv[])
cout << endl << "PARSING INPUT" << endl; cout << endl << "PARSING INPUT" << endl;
} }
const char *flag_dvp = flags["DISABLE_VIRTUAL_PINS"]; const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
if (flag_dvp) disable_virtual_pins = strcmp(flag_dvp,"true")==0; 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. */ /* Parse the input. Make the pform. */
int rc = pform_parse(argv[optind]); int rc = pform_parse(argv[optind]);

View File

@ -175,6 +175,12 @@ Link* find_next_output(Link*lnk)
void NetPins::devirtualize_pins(void) void NetPins::devirtualize_pins(void)
{ {
if (pins_) return; 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; if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
pins_ = new Link[npins_]; pins_ = new Link[npins_];
@ -263,6 +269,11 @@ bool NetPins::is_linked(void)
NetObj::NetObj(NetScope*s, perm_string n, unsigned np) NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0) : 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() NetObj::~NetObj()
@ -568,12 +579,14 @@ static unsigned calculate_count(long s, long e)
{ {
unsigned long r; unsigned long r;
if (s >= e) { if (s >= e) {
r = s - e + 1; r = s - e;
} else { } else {
r = e - s + 1; r = e - s;
} }
assert (r <= UINT_MAX); if (r >= UINT_MAX) {
return r; return 0;
}
return r + 1;
} }
NetNet::NetNet(NetScope*s, perm_string n, Type t, 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), discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0) 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; verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE; Link::DIR dir = Link::PASSIVE;
@ -778,7 +795,9 @@ bool NetNet::array_addr_swapped() const
unsigned NetNet::array_count() 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 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); void set_default_init(verinum::V val);
bool is_linked(); bool is_linked();
bool pins_are_virtual(void) const; bool pins_are_virtual(void) const;
void devirtualize_pins(void);
private: private:
Link*pins_; Link*pins_;
void devirtualize_pins(void);
const unsigned npins_; const unsigned npins_;
Link::DIR default_dir_; Link::DIR default_dir_;
verinum::V default_init_; 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) extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
{ {
assert(word < net->array_words); assert(word < net->array_words);
if (net->array_words > 1) if (net->array_words > 1) {
return net->pins[word]; if (net->pins) {
else return net->pins[word];
} else {
cerr << "AACK! ivl_signal_nex() returning NULL" << endl;
return NULL;
}
} else {
return net->pin; return net->pin;
}
} }
extern "C" int ivl_signal_msb(ivl_signal_t net) 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()); assert(obj->array_words == net->pin_count());
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: " if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
"t-dll creating nexus array " << obj->array_words << " long" << endl; "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) if (obj->array_words > 1)
obj->pins = new ivl_nexus_t[obj->array_words]; obj->pins = new ivl_nexus_t[obj->array_words];