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:
parent
932aa49b38
commit
3a18bda8ee
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
9
main.cc
9
main.cc
|
|
@ -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]);
|
||||||
|
|
|
||||||
31
netlist.cc
31
netlist.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
12
t-dll-api.cc
12
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)
|
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)
|
||||||
|
|
|
||||||
6
t-dll.cc
6
t-dll.cc
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue