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:
parent
5ec7731e04
commit
b795d8c1d8
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
5
main.cc
5
main.cc
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
42
netlist.cc
42
netlist.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
/* =========
|
||||
|
|
|
|||
7
t-dll.cc
7
t-dll.cc
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue