From 3a18bda8ee3ade49867d44b3fc0df7ae87916b69 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Wed, 11 Mar 2009 09:18:30 -0700 Subject: [PATCH] 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 --- compiler.h | 3 +++ elab_sig.cc | 6 ++++-- main.cc | 9 ++++++--- netlist.cc | 31 +++++++++++++++++++++++++------ netlist.h | 2 +- t-dll-api.cc | 12 +++++++++--- t-dll.cc | 6 ++++++ 7 files changed, 54 insertions(+), 15 deletions(-) diff --git a/compiler.h b/compiler.h index 7454172ba..c70c50d2b 100644 --- a/compiler.h +++ b/compiler.h @@ -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; diff --git a/elab_sig.cc b/elab_sig.cc index 919767465..1b26ca920 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -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; diff --git a/main.cc b/main.cc index 79a88e40c..f4b18ab01 100644 --- a/main.cc +++ b/main.cc @@ -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]); diff --git a/netlist.cc b/netlist.cc index 6ec49d43b..d76b6d443 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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 diff --git a/netlist.h b/netlist.h index b85ebb13b..23c613f4b 100644 --- a/netlist.h +++ b/netlist.h @@ -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_; diff --git a/t-dll-api.cc b/t-dll-api.cc index fbce632eb..9b3cae302 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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) diff --git a/t-dll.cc b/t-dll.cc index 3cdcec1a5..a66feefb3 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -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];