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 */
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
9
main.cc
9
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]);
|
||||
|
|
|
|||
31
netlist.cc
31
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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
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)
|
||||
{
|
||||
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)
|
||||
|
|
|
|||
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());
|
||||
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];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue