Virtualize Pins until needed

Reduces resource usage when compiling large memories.
Normal usage patterns still create large nexus arrays
in t-dll.cc:dll_target::signal().

This patch is extensively tested; it shouldn't break anything.

The existing debug "optimizer" flag is (ab)used to control
message printing when large (>1000 element) arrays are
devirtualized or nexus-ized.

The new global variable disable_virtual_pins is available
to force allocation of Pin arrays when they are declared,
but no user interface is provided.

See extensive discussion on iverilog-devel, March 4-5 2009,
title "pr2023076: large memories".
(cherry picked from commit 5bc41e1a17)
This commit is contained in:
Larry Doolittle 2009-03-05 17:44:11 -08:00 committed by Stephen Williams
parent 5ec7731e04
commit b795d8c1d8
6 changed files with 64 additions and 7 deletions

View File

@ -89,6 +89,9 @@ extern bool debug_elab_pexpr;
extern bool debug_synth2;
extern bool debug_optimizer;
/* Possibly temporary flag to control virtualization of pin arrays */
extern bool disable_virtual_pins;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;

View File

@ -208,8 +208,12 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " scope=" << scope_path(scope());
o << " #(" << rise_time() << "," << fall_time() << ","
<< decay_time() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count()
<< " init=";
<< " pin_count=" << pin_count();
if (pins_are_virtual()) {
o << " pins_are_virtual" << endl;
return;
}
o << " init=";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << pin(idx-1).get_init();

View File

@ -128,6 +128,11 @@ bool debug_elab_pexpr = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
/*
* Miscellaneous flags.
*/
bool disable_virtual_pins = false; // XXX needs a way for user to set
/*
* Verbose messages enabled.
*/

View File

@ -172,26 +172,45 @@ Link* find_next_output(Link*lnk)
return 0;
}
NetPins::NetPins(unsigned npins)
: npins_(npins)
void NetPins::devirtualize_pins(void)
{
if (pins_) return;
if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
pins_ = new Link[npins_];
pins_[0].pin_zero_ = true;
pins_[0].node_ = this;
pins_[0].dir_ = default_dir_;
pins_[0].init_ = default_init_;
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
pins_[idx].pin_zero_ = false;
pins_[idx].pin_ = idx;
pins_[idx].dir_ = default_dir_;
pins_[idx].init_ = default_init_;
}
}
bool NetPins::pins_are_virtual(void) const
{
return pins_ == NULL;
}
NetPins::NetPins(unsigned npins)
: npins_(npins)
{
pins_ = NULL; // Wait until someone asks.
if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
}
NetPins::~NetPins()
{
delete[]pins_;
if (pins_) delete[]pins_;
}
Link& NetPins::pin(unsigned idx)
{
if (!pins_) devirtualize_pins();
if (idx >= npins_) {
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
<< " out of bounds("<<npins_<<")" << endl;
@ -207,11 +226,22 @@ Link& NetPins::pin(unsigned idx)
const Link& NetPins::pin(unsigned idx) const
{
assert(pins_);
assert(idx < npins_);
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
return pins_[idx];
}
void NetPins::set_default_dir(Link::DIR d)
{
default_dir_ = d;
}
void NetPins::set_default_init(verinum::V val)
{
default_init_ = val;
}
bool NetPins::is_linked(void)
{
bool linked_flag = false;
@ -479,7 +509,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
void NetNet::initialize_value_and_dir(verinum::V init_value, Link::DIR dir)
{
if (1) {
if (pins_are_virtual()) {
if (0) cerr << "NetNet setting Link default value and dir" << endl;
set_default_init(init_value);
set_default_dir(dir);
} else {
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);

View File

@ -193,11 +193,17 @@ class NetPins : public LineInfo {
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
void set_default_dir(Link::DIR d);
void set_default_init(verinum::V val);
bool is_linked();
bool pins_are_virtual(void) const;
private:
Link*pins_;
void devirtualize_pins(void);
const unsigned npins_;
Link::DIR default_dir_;
verinum::V default_init_;
};
/* =========

View File

@ -2560,12 +2560,16 @@ void dll_target::signal(const NetNet*net)
obj->array_base = net->array_first();
obj->array_words = net->array_count();
obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0;
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)
obj->pins = new ivl_nexus_t[obj->array_words];
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus();
const Nexus*nex = net->pins_are_virtual() ? 0 : net->pin(idx).nexus();
if (nex == 0) {
// Special case: This pin is connected to
// nothing. This can happen, for example, if the
@ -2597,6 +2601,7 @@ void dll_target::signal(const NetNet*net)
obj->pin = tmp;
}
}
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: t-dll done with big nexus array" << endl;
}
bool dll_target::signal_paths(const NetNet*net)