From b795d8c1d800cf6eebcff9b6dfe72fc4c618d2fe Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Thu, 5 Mar 2009 17:44:11 -0800 Subject: [PATCH] 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 5bc41e1a177783cd078e310ede17700ef8cbe170) --- compiler.h | 3 +++ design_dump.cc | 8 ++++++-- main.cc | 5 +++++ netlist.cc | 42 ++++++++++++++++++++++++++++++++++++++---- netlist.h | 6 ++++++ t-dll.cc | 7 ++++++- 6 files changed, 64 insertions(+), 7 deletions(-) diff --git a/compiler.h b/compiler.h index 0524c6abe..7454172ba 100644 --- a/compiler.h +++ b/compiler.h @@ -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; diff --git a/design_dump.cc b/design_dump.cc index e6c3ae769..3c63722bf 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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(); diff --git a/main.cc b/main.cc index f947105b1..3ba8774f1 100644 --- a/main.cc +++ b/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. */ diff --git a/netlist.cc b/netlist.cc index e781a74e9..6c86daa00 100644 --- a/netlist.cc +++ b/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("<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)