Merge pull request #779 from KLayout/lvs-memory-problem

Lvs memory problem
This commit is contained in:
Matthias Köfferlein 2021-04-27 07:39:37 +02:00 committed by GitHub
commit e5e2450cb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 646 additions and 64 deletions

View File

@ -2,7 +2,63 @@ klayout (0.27-1) unstable; urgency=low
* NOT RELEASED YET
-- Matthias Köfferlein <matthias@koefferlein.de> Sun, 05 Apr 2020 13:30:58 +0200
-- Matthias Köfferlein <matthias@koefferlein.de> Wed, 21 Apr 2021 21:39:50 +0200
klayout (0.26.12-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Wed, 21 Apr 2021 21:39:50 +0200
klayout (0.26.11-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Thu, 25 Feb 2021 22:06:53 +0100
klayout (0.26.10-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Tue, 02 Feb 2021 22:54:19 +0100
klayout (0.26.9-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Fri, 27 Nov 2020 18:38:20 +0100
klayout (0.26.8-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Mon, 14 Sep 2020 20:30:57 +0200
klayout (0.26.7-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Tue, 07 Jul 2020 18:27:53 +0200
klayout (0.26.6-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Thu, 28 May 2020 00:39:24 +0200
klayout (0.26.5-1) unstable; urgency=low
* New features and bugfixes
- See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Sat, 02 May 2020 13:26:24 +0200
klayout (0.26.4-1) unstable; urgency=low

View File

@ -598,15 +598,7 @@ Cell::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat,
}
db::mem_stat (stat, purpose, cat, m_bboxes, true, (void *) this);
db::mem_stat (stat, MemStatistics::Instances, cat, m_instances, true, (void *) this);
// iterate the shapes separately so we can use the layer for the category
for (shapes_map::const_iterator i = m_shapes_map.begin (); i != m_shapes_map.end (); ++i) {
db::mem_stat (stat, MemStatistics::ShapesInfo, (int) i->first, i->first, false, (void *) this);
db::mem_stat (stat, MemStatistics::ShapesInfo, (int) i->first, i->second, false, (void *) this);
#ifdef __GNUCC__
stat->add (std::_Rb_tree_node_base, (void *) &i->first, sizeof (std::_Rb_tree_node_base), sizeof (std::_Rb_tree_node_base), (void *) &v, purpose, cat);
#endif
}
db::mem_stat (stat, MemStatistics::ShapesInfo, cat, m_shapes_map, true, (void *) this);
}
void

View File

@ -31,6 +31,7 @@
#include "dbSubCircuit.h"
#include "dbNetlistUtils.h"
#include "dbPolygon.h"
#include "dbMemStatistics.h"
#include "tlObject.h"
#include "tlObjectCollection.h"
@ -749,6 +750,32 @@ public:
*/
void blank ();
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_boundary, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_nets, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_pins, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_pin_by_id, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_devices, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_subcircuits, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_pin_refs, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_device_by_id, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_subcircuit_by_id, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_net_by_cluster_id, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_device_by_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_subcircuit_by_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_net_by_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_refs, true, (void *) this);
}
private:
friend class Netlist;
friend class Net;
@ -798,6 +825,14 @@ private:
void nets_changed ();
};
/**
* @brief Memory statistics for Circuit
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const Circuit &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif

View File

@ -28,6 +28,7 @@
#include "dbPoint.h"
#include "dbVector.h"
#include "dbTrans.h"
#include "dbMemStatistics.h"
#include "tlObject.h"
@ -349,6 +350,23 @@ public:
return m_other_abstracts;
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_trans, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_terminal_refs, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_parameters, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_other_abstracts, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_reconnected_terminals, true, (void *) this);
}
private:
friend class Circuit;
friend class Net;
@ -396,6 +414,14 @@ private:
void init_terminal_routes ();
};
/**
* @brief Memory statistics for Device
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const Device &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif

View File

@ -26,6 +26,7 @@
#include "dbCommon.h"
#include "dbNet.h"
#include "dbPoint.h"
#include "dbMemStatistics.h"
#include "tlObject.h"
@ -144,6 +145,19 @@ public:
*/
void set_cluster_id_for_terminal (size_t terminal_id, size_t cluster_id);
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_terminal_cluster_ids, true, (void *) this);
}
private:
friend class Netlist;
@ -159,6 +173,14 @@ private:
void set_netlist (Netlist *netlist);
};
/**
* @brief Memory statistics for LayoutToNetlist
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const DeviceAbstract &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif

View File

@ -24,6 +24,7 @@
#define _HDR_dbDeviceClass
#include "dbCommon.h"
#include "dbMemStatistics.h"
#include "gsiObject.h"
#include "tlObject.h"
@ -102,6 +103,19 @@ public:
return m_id;
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_description, true, (void *) this);
}
private:
friend class DeviceClass;
@ -114,6 +128,14 @@ private:
}
};
/**
* @brief Memory statistics for DeviceTerminalDefinition
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const DeviceTerminalDefinition &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
/**
* @brief A device parameter definition
*/
@ -224,6 +246,19 @@ public:
return m_id;
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_description, true, (void *) this);
}
private:
friend class DeviceClass;
@ -239,6 +274,14 @@ private:
}
};
/**
* @brief Memory statistics for DeviceParameterDefinition
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const DeviceParameterDefinition &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
/**
* @brief A device parameter compare delegate
*
@ -598,6 +641,21 @@ public:
return mp_pc_delegate.get ();
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_description, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_terminal_definitions, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_parameter_definitions, true, (void *) this);
}
private:
friend class Netlist;
@ -614,6 +672,14 @@ private:
}
};
/**
* @brief Memory statistics for DeviceClass
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const DeviceClass &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
/**
* @brief A device class template
*

View File

@ -414,6 +414,19 @@ local_cluster<T>::ensure_sorted ()
m_needs_update = false;
}
template <class T>
void
local_cluster<T>::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_shapes, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_attrs, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_global_nets, true, (void *) this);
}
template <class T>
class DB_PUBLIC hnp_interaction_receiver
: public box_scanner_receiver2<T, unsigned int, T, unsigned int>
@ -786,6 +799,20 @@ local_clusters<T>::ensure_sorted ()
m_needs_update = false;
}
template <class T>
void
local_clusters<T>::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_needs_update, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_bbox, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_clusters, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_next_dummy_id, true, (void *) this);
}
namespace
{
@ -1210,6 +1237,21 @@ connected_clusters<T>::find_cluster_with_connection (const ClusterInstance &inst
}
}
template <class T>
void
connected_clusters<T>::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
local_clusters<T>::mem_stat (stat, purpose, cat, true, parent);
db::mem_stat (stat, purpose, cat, m_connections, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_rev_connections, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_connected_clusters, true, (void *) this);
}
// explicit instantiations
template class DB_PUBLIC connected_clusters<db::NetShape>;
template class DB_PUBLIC connected_clusters<db::PolygonRef>;
@ -1290,6 +1332,17 @@ void hier_clusters<T>::clear ()
m_per_cell_clusters.clear ();
}
template <class T>
void
hier_clusters<T>::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_per_cell_clusters, true, (void *) this);
}
template <class T>
void
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
@ -1467,7 +1520,7 @@ private:
join_set_list m_cm2join_sets;
std::list<ClusterInstanceInteraction> m_ci_interactions;
std::map<InteractionKeyForClustersType, std::vector<std::pair<size_t, size_t> > > m_interaction_cache_for_clusters;
instance_interaction_cache_type *mp_instance_interaction_cache;
typename hier_clusters<T>::instance_interaction_cache_type *mp_instance_interaction_cache;
/**
* @brief Investigate a pair of instances
@ -1488,7 +1541,7 @@ private:
void consider_instance_pair (const box_type &common,
const db::Instance &i1, const db::ICplxTrans &t1, const db::CellInstArray::iterator &i1element,
const db::Instance &i2, const db::ICplxTrans &t2, const db::CellInstArray::iterator &i2element,
std::list<std::pair<ClusterInstance, ClusterInstance> > &interacting_clusters)
cluster_instance_pair_list_type &interacting_clusters)
{
if (is_breakout_cell (mp_breakout_cells, i1.cell_index ()) || is_breakout_cell (mp_breakout_cells, i2.cell_index ())) {
return;
@ -1510,7 +1563,7 @@ private:
db::ICplxTrans i1t, i2t;
bool fill_cache = false;
// Cache is only used for single instances, non-iterated, simple or regular arrays.
// Cache is only used for single instances or simple and regular arrays.
if ((! i1element.at_end () || i1.size () == 1 || ! i1.is_iterated_array ()) &&
(! i2element.at_end () || i2.size () == 1 || ! i2.is_iterated_array ())) {
@ -1525,12 +1578,12 @@ private:
i2.cell_index (), (! i2element.at_end () || i2.size () == 1) ? 0 : i2.cell_inst ().delegate (),
cache_norm, cache_norm * tt2);
instance_interaction_cache_type::iterator ii = mp_instance_interaction_cache->find (ii_key);
if (ii != mp_instance_interaction_cache->end ()) {
const cluster_instance_pair_list_type *cached = mp_instance_interaction_cache->find (ii_key);
if (cached) {
// use cached interactions
interacting_clusters = ii->second;
for (std::list<std::pair<ClusterInstance, ClusterInstance> >::iterator i = interacting_clusters.begin (); i != interacting_clusters.end (); ++i) {
interacting_clusters = *cached;
for (cluster_instance_pair_list_type::iterator i = interacting_clusters.begin (); i != interacting_clusters.end (); ++i) {
// translate the property IDs
i->first.set_inst_prop_id (i1.prop_id ());
i->first.transform (i1t);
@ -1596,6 +1649,22 @@ private:
}
// dive into cell of ii1
const db::Cell &cell1 = mp_layout->cell (i1.cell_index ());
for (db::Cell::touching_iterator jj1 = cell1.begin_touching (common12.transformed (tt1.inverted ())); ! jj1.at_end (); ++jj1) {
std::list<std::pair<ClusterInstance, ClusterInstance> > ii_interactions;
consider_instance_pair (common12, *jj1, tt1, db::CellInstArray::iterator (), i2, t2, ii2, ii_interactions);
for (std::list<std::pair<ClusterInstance, ClusterInstance> >::iterator i = ii_interactions.begin (); i != ii_interactions.end (); ++i) {
propagate_cluster_inst (i->first, i1.cell_index (), i1t, i1.prop_id ());
}
ii_interactions.unique ();
interacting_clusters.splice (interacting_clusters.end (), ii_interactions, ii_interactions.begin (), ii_interactions.end ());
}
}
if (! i2element.at_end ()) {
@ -1604,27 +1673,6 @@ private:
}
box_type common1 = ib1 & b2 & common;
if (! common1.empty ()) {
// dive into cell of ii1
const db::Cell &cell1 = mp_layout->cell (i1.cell_index ());
for (db::Cell::touching_iterator jj1 = cell1.begin_touching (common1.transformed (tt1.inverted ())); ! jj1.at_end (); ++jj1) {
std::list<std::pair<ClusterInstance, ClusterInstance> > ii_interactions;
consider_instance_pair (common1, *jj1, tt1, db::CellInstArray::iterator (), i2, t2, i2element, ii_interactions);
for (std::list<std::pair<ClusterInstance, ClusterInstance> >::iterator i = ii_interactions.begin (); i != ii_interactions.end (); ++i) {
propagate_cluster_inst (i->first, i1.cell_index (), i1t, i1.prop_id ());
}
ii_interactions.unique ();
interacting_clusters.splice (interacting_clusters.end (), ii_interactions, ii_interactions.begin (), ii_interactions.end ());
}
}
if (! i1element.at_end ()) {
break;
}
@ -1653,7 +1701,7 @@ private:
i->second.transform (i2ti);
}
cluster_instance_pair_list_type &cached = (*mp_instance_interaction_cache) [ii_key];
cluster_instance_pair_list_type &cached = mp_instance_interaction_cache->insert (ii_key);
cached.insert (cached.end (), sorted_interactions.begin (), sorted_interactions.end ());
}
@ -2187,6 +2235,10 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
}
if (tl::verbosity () >= 51) {
tl::info << "Cluster build cache statistics: size=" << instance_interaction_cache.size () << ", hits=" << instance_interaction_cache.hits () << ", misses=" << instance_interaction_cache.misses ();
}
}
template <class T>

View File

@ -365,6 +365,11 @@ public:
*/
void set_global_nets (const global_nets &gn);
/**
* @brief Collect memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const;
private:
template <typename> friend class local_clusters;
template <typename> friend class hnp_interaction_receiver;
@ -392,6 +397,15 @@ private:
size_t m_size;
};
/**
* @brief Memory statistics for local_cluster<T>
*/
template <class T>
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const local_cluster<T> &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
/**
* @brief A box converter for the local_cluster class
*/
@ -533,6 +547,19 @@ public:
return id > m_clusters.size ();
}
/**
* @brief Gets the number of clusters
*/
size_t size () const
{
return m_clusters.size ();
}
/**
* @brief Collect memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const;
private:
void ensure_sorted ();
@ -544,6 +571,15 @@ private:
void apply_attr_equivalences (const tl::equivalence_clusters<size_t> &attr_equivalence);
};
/**
* @brief Memory statistics for local_clusters<T>
*/
template <class T>
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const local_clusters<T> &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
/**
* @brief The instance information for a cluster
*/
@ -859,8 +895,6 @@ struct InstanceToInstanceInteraction
db::ICplxTrans t21;
};
typedef std::map<InstanceToInstanceInteraction, cluster_instance_pair_list_type> instance_interaction_cache_type;
template <class T> class hier_clusters;
template <class T> class connected_clusters;
@ -1013,6 +1047,11 @@ public:
m_connected_clusters.insert (id);
}
/**
* @brief Collect memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const;
private:
template<typename> friend class connected_clusters_iterator;
@ -1021,6 +1060,15 @@ private:
std::set<id_type> m_connected_clusters;
};
/**
* @brief Memory statistics for connected_clusters<T>
*/
template <class T>
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const connected_clusters<T> &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
template <typename> class cell_clusters_box_converter;
/**
@ -1034,7 +1082,55 @@ class DB_PUBLIC_TEMPLATE hier_clusters
{
public:
typedef typename local_cluster<T>::box_type box_type;
typedef std::map<InstanceToInstanceInteraction, cluster_instance_pair_list_type> instance_interaction_cache_type;
/**
* @brief An object representing the instance interaction cache
*/
class instance_interaction_cache
{
public:
instance_interaction_cache ()
: m_hits (0), m_misses (0)
{ }
size_t size () const
{
return m_map.size ();
}
size_t hits () const
{
return m_hits;
}
size_t misses () const
{
return m_misses;
}
const cluster_instance_pair_list_type *find (const InstanceToInstanceInteraction &key) const
{
std::map<InstanceToInstanceInteraction, cluster_instance_pair_list_type>::const_iterator i = m_map.find (key);
if (i == m_map.end ()) {
++m_misses;
return 0;
} else {
++m_hits;
return &i->second;
}
}
cluster_instance_pair_list_type &insert (const InstanceToInstanceInteraction &key)
{
return m_map [key];
}
private:
mutable size_t m_hits, m_misses;
std::map<InstanceToInstanceInteraction, cluster_instance_pair_list_type> m_map;
};
typedef instance_interaction_cache instance_interaction_cache_type;
/**
* @brief Creates an empty set of clusters
@ -1094,6 +1190,11 @@ public:
*/
size_t propagate_cluster_inst (const db::Layout &layout, const Cell &cell, const ClusterInstance &ci, db::cell_index_type parent_ci, bool with_self);
/**
* @brief Collect memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const;
private:
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache);

View File

@ -397,9 +397,41 @@ void LayoutToNetlist::extract_netlist ()
netex.set_include_floating_subcircuits (m_include_floating_subcircuits);
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters);
if (tl::verbosity () >= 41) {
MemStatisticsCollector m (false);
mem_stat (&m, db::MemStatistics::None, 0);
m.print ();
}
m_netlist_extracted = true;
}
void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_description, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_original_file, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_filename, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_net_clusters, true, (void *) this);
db::mem_stat (stat, purpose, cat, mp_netlist, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_dlrefs, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_named_regions, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_name_of_layer, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_net_names, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_net_names_per_cell, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_nets, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_nets_per_cell, true, (void *) this);
m_net_clusters.mem_stat (stat, MemStatistics::LayoutToNetlist, cat, true, (void *) this);
if (mp_netlist.get ()) {
db::mem_stat (stat, MemStatistics::Netlist, cat, *mp_netlist, false, (void *) this);
}
}
void LayoutToNetlist::set_netlist_extracted ()
{
m_netlist_extracted = true;

View File

@ -893,6 +893,11 @@ public:
*/
static db::LayoutToNetlist *create_from_file (const std::string &path);
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const;
private:
// no copying
LayoutToNetlist (const db::LayoutToNetlist &other);
@ -971,6 +976,14 @@ private:
virtual void link_nets (const db::Net *net, const db::Net *with);
};
/**
* @brief Memory statistics for LayoutToNetlist
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const LayoutToNetlist &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
namespace tl

View File

@ -100,14 +100,16 @@ void
MemStatisticsCollector::print ()
{
std::map<purpose_t, std::string> p2s;
p2s[None] = "(none) ";
p2s[LayoutInfo] = "Layout info ";
p2s[CellInfo] = "Cell info ";
p2s[Instances] = "Instances ";
p2s[InstTrees] = "Instance trees ";
p2s[ShapesInfo] = "Shapes info ";
p2s[ShapesCache] = "Shapes cache ";
p2s[ShapeTrees] = "Shape trees ";
p2s[None] = "(none) ";
p2s[LayoutInfo] = "Layout info ";
p2s[CellInfo] = "Cell info ";
p2s[Instances] = "Instances ";
p2s[InstTrees] = "Instance trees ";
p2s[ShapesInfo] = "Shapes info ";
p2s[ShapesCache] = "Shapes cache ";
p2s[ShapeTrees] = "Shape trees ";
p2s[Netlist] = "Netlist ";
p2s[LayoutToNetlist] = "Netlist layout ";
if (m_detailed) {

View File

@ -26,6 +26,7 @@
#define HDR_dbMemStatistics
#include "dbCommon.h"
#include "tlObjectCollection.h"
#include <stdio.h>
#include <string>
@ -33,6 +34,8 @@
#include <map>
#include <set>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <typeinfo>
#include "tlReuseVector.h"
@ -64,7 +67,9 @@ public:
InstTrees,
ShapesInfo,
ShapesCache,
ShapeTrees
ShapeTrees,
Netlist,
LayoutToNetlist
};
/**
@ -120,7 +125,7 @@ template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const tl::reuse_vector<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (tl::reuse_vector<X>), (void *) &v, sizeof (tl::reuse_vector<X>), sizeof (tl::reuse_vector<X>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
if (! v.empty ()) {
stat->add (typeid (X[]), (void *) v.begin ().operator-> (), sizeof (X) * v.capacity (), sizeof (X) * v.size (), (void *) &v, purpose, cat);
@ -137,7 +142,7 @@ template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const tl::vector<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (tl::vector<X>), (void *) &v, sizeof (tl::vector<X>), sizeof (tl::vector<X>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
if (! v.empty ()) {
stat->add (typeid (X[]), (void *) &v.front (), sizeof (X) * v.capacity (), sizeof (X) * v.size (), (void *) &v, purpose, cat);
@ -151,7 +156,7 @@ template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::vector<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (std::vector<X>), (void *) &v, sizeof (std::vector<X>), sizeof (std::vector<X>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
if (! v.empty ()) {
stat->add (typeid (X[]), (void *) &v.front (), sizeof (X) * v.capacity (), sizeof (X) * v.size (), (void *) &v, purpose, cat);
@ -167,41 +172,68 @@ template <class X, class Y>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::map<X, Y> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (std::map<X, Y>), (void *) &v, sizeof (std::map<X, Y>), sizeof (std::map<X, Y>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
for (typename std::map<X, Y>::const_iterator i = v.begin (); i != v.end (); ++i) {
mem_stat (stat, purpose, cat, i->first, false, (void *) &v);
mem_stat (stat, purpose, cat, i->second, false, (void *) &v);
#ifdef __GNUCC__
stat->add (std::_Rb_tree_node_base, (void *) &i->first, sizeof (std::_Rb_tree_node_base), sizeof (std::_Rb_tree_node_base), (void *) &v, purpose, cat);
#ifdef __GLIBCXX__
stat->add (typeid (std::_Rb_tree_node_base), (void *) &i->first, sizeof (std::_Rb_tree_node_base), sizeof (std::_Rb_tree_node_base), (void *) &v, purpose, cat);
#endif
}
}
template <class X, class Y>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::unordered_map<X, Y> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
for (typename std::unordered_map<X, Y>::const_iterator i = v.begin (); i != v.end (); ++i) {
mem_stat (stat, purpose, cat, i->first, false, (void *) &v);
mem_stat (stat, purpose, cat, i->second, false, (void *) &v);
// TODO: add intrinsic overhead
}
}
template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::set<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (std::set<X>), (void *) &v, sizeof (std::set<X>), sizeof (std::set<X>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
for (typename std::set<X>::const_iterator i = v.begin (); i != v.end (); ++i) {
mem_stat (stat, purpose, cat, *i, false, (void *) &v);
#ifdef __GNUCC__
stat->add (std::_Rb_tree_node_base, (void *) &i.operator-> (), sizeof (std::_Rb_tree_node_base), sizeof (std::_Rb_tree_node_base), (void *) &v, purpose, cat);
#ifdef __GLIBCXX__
// NOTE: the pointer is only an approximation
stat->add (typeid (std::_Rb_tree_node_base), (void *) i.operator-> (), sizeof (std::_Rb_tree_node_base), sizeof (std::_Rb_tree_node_base), (void *) &v, purpose, cat);
#endif
}
}
template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::unordered_set<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
for (typename std::unordered_set<X>::const_iterator i = v.begin (); i != v.end (); ++i) {
mem_stat (stat, purpose, cat, *i, false, (void *) &v);
// TODO: add intrinsic overhead
}
}
template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::list<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (std::list<X>), (void *) &v, sizeof (std::list<X>), sizeof (std::list<X>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
for (typename std::list<X>::const_iterator i = v.begin (); i != v.end (); ++i) {
mem_stat (stat, purpose, cat, *i, false, (void *) &v);
#ifdef __GNUCC__
stat->add (std::_List_node_base, (void *) &i.operator-> (), sizeof (std::_List_node_base), sizeof (std::_List_node_base), (void *) &v, purpose, cat);
#ifdef __GLIBCXX__
// NOTE: the pointer is only an approximation
stat->add (typeid (std::__detail::_List_node_base), (void *) i.operator-> (), sizeof (std::__detail::_List_node_base), sizeof (std::__detail::_List_node_base), (void *) &v, purpose, cat);
#endif
}
}
@ -210,12 +242,35 @@ template <class X, class Y>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const std::pair<X, Y> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (std::pair<X, Y>), (void *) &v, sizeof (std::pair<X, Y>), sizeof (std::pair<X, Y>), parent, purpose, cat);
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
mem_stat (stat, purpose, cat, v.first, true, (void *) &v);
mem_stat (stat, purpose, cat, v.second, true, (void *) &v);
}
template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const tl::shared_collection<X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
size_t intrinsic = sizeof (typename tl::shared_collection<X>::holder_type) * v.size ();
stat->add (typeid (typename tl::shared_collection<X>::holder_type), (void *) &v, intrinsic, intrinsic, (void *) &v, purpose, cat);
for (typename tl::shared_collection<X>::const_iterator i = v.begin (); i != v.end (); ++i) {
mem_stat (stat, purpose, cat, *i, false, (void *) &v);
}
}
template <class X>
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const tl::weak_collection <X> &v, bool no_self = false, void *parent = 0)
{
if (! no_self) {
stat->add (typeid (v), (void *) &v, sizeof (v), sizeof (v), parent, purpose, cat);
}
size_t intrinsic = sizeof (typename tl::weak_collection<X>::holder_type) * v.size ();
stat->add (typeid (typename tl::weak_collection<X>::holder_type), (void *) &v, intrinsic, intrinsic, (void *) &v, purpose, cat);
}
}
#endif

View File

@ -25,6 +25,7 @@
#include "dbCommon.h"
#include "dbNetlistObject.h"
#include "dbMemStatistics.h"
#include "tlObject.h"
@ -664,6 +665,21 @@ public:
return m_terminals.size ();
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_terminals, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_pins, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_subcircuit_pins, true, (void *) this);
}
private:
friend class Circuit;
@ -677,6 +693,14 @@ private:
void set_circuit (Circuit *circuit);
};
/**
* @brief Memory statistics for Net
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const Net &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif

View File

@ -103,6 +103,24 @@ Netlist &Netlist::operator= (const Netlist &other)
return *this;
}
void Netlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_circuits, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_device_classes, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_device_abstracts, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_top_down_circuits, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_child_circuits, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_parent_circuits, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_circuit_by_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_circuit_by_cell_index, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_device_abstract_by_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_device_abstract_by_cell_index, true, (void *) this);
}
void Netlist::set_case_sensitive (bool f)
{
m_case_sensitive = f;

View File

@ -533,6 +533,11 @@ public:
return normalize_name (is_case_sensitive (), n);
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const;
private:
friend class Circuit;
friend class DeviceAbstract;
@ -567,6 +572,14 @@ private:
const tl::vector<Circuit *> &parent_circuits (Circuit *circuit);
};
/**
* @brief Memory statistics for LayoutToNetlist
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const Netlist &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
/**
* @brief A helper class using RAII for safe locking/unlocking
*/

View File

@ -24,6 +24,12 @@
#define _HDR_dbNetlistUtils
#include "dbCommon.h"
#include "dbTypes.h"
#include "dbMemStatistics.h"
#include <map>
#include <string>
#include <set>
namespace db
{
@ -102,6 +108,22 @@ public:
return m == m_map.end () ? 0 : m->second;
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_map, true, (void *) this);
for (typename std::map<attr_type, value_type *>::const_iterator i = m_map.begin (); i != m_map.end (); ++i) {
db::mem_stat (stat, purpose, cat, *i->second, false, (void *) this);
}
}
private:
T *mp_self;
I (T::*m_bi) ();
@ -122,6 +144,15 @@ private:
}
};
/**
* @brief Memory statistics for object_by_attr
*/
template <class T, class I, class ATTR>
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const object_by_attr<T, I, ATTR> &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif

View File

@ -25,6 +25,7 @@
#include "dbCommon.h"
#include "dbNetlistObject.h"
#include "dbMemStatistics.h"
#include <string>
@ -81,6 +82,18 @@ public:
m_name = name;
}
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
}
private:
friend class Circuit;
@ -93,6 +106,14 @@ private:
}
};
/**
* @brief Memory statistics for Pin
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const Pin &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif

View File

@ -26,6 +26,7 @@
#include "dbCommon.h"
#include "dbTrans.h"
#include "dbNet.h"
#include "dbMemStatistics.h"
#include "tlObject.h"
@ -194,6 +195,20 @@ public:
*/
void connect_pin (size_t pin_id, Net *net);
/**
* @brief Generate memory statistics
*/
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
{
if (! no_self) {
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
db::mem_stat (stat, purpose, cat, m_name, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_trans, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_pin_refs, true, (void *) this);
}
private:
friend class Circuit;
friend class Net;
@ -232,6 +247,14 @@ private:
}
};
/**
* @brief Memory statistics for SubCircuit
*/
inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const SubCircuit &x, bool no_self, void *parent)
{
x.mem_stat (stat, purpose, cat, no_self, parent);
}
}
#endif