mirror of https://github.com/KLayout/klayout.git
Merge branch 'master' into feedback
This commit is contained in:
commit
7c3c631515
|
|
@ -2,7 +2,7 @@ klayout (0.27-1) unstable; urgency=low
|
|||
|
||||
* NOT RELEASED YET
|
||||
|
||||
-- Matthias Köfferlein <matthias@koefferlein.de> Wed, 21 Apr 2021 21:39:50 +0200
|
||||
-- Matthias Köfferlein <matthias@koefferlein.de> Tue, 27 Apr 2021 07:38:15 +0200
|
||||
|
||||
klayout (0.26.12-1) unstable; urgency=low
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ namespace db
|
|||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// Don't cache instance to instance interaction sets beyond this size
|
||||
const size_t instance_to_instance_cache_set_size_threshold = 10000;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
template <class Shape, class Trans> void insert_transformed (db::Layout &layout, db::Shapes &shapes, const Shape &s, const Trans &t);
|
||||
|
||||
template <class Trans> void insert_transformed (db::Layout &layout, db::Shapes &shapes, const db::PolygonRef &s, const Trans &t)
|
||||
|
|
@ -311,6 +316,54 @@ bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned
|
|||
}
|
||||
}
|
||||
|
||||
bool Connectivity::interacts (const std::set<unsigned int> &la, const std::set<unsigned int> &lb) const
|
||||
{
|
||||
for (std::set<unsigned int>::const_iterator i = la.begin (); i != la.end (); ++i) {
|
||||
db::Connectivity::layer_iterator je = end_connected (*i);
|
||||
for (db::Connectivity::layer_iterator j = begin_connected (*i); j != je; ++j) {
|
||||
if (lb.find (*j) != lb.end ()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Connectivity::interact (const db::Cell &a, const db::Cell &b) const
|
||||
{
|
||||
for (std::map<unsigned int, layers_type>::const_iterator i = m_connected.begin (); i != m_connected.end (); ++i) {
|
||||
if (! a.bbox (i->first).empty ()) {
|
||||
for (layers_type::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
if (! b.bbox (*j).empty ()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool Connectivity::interact (const db::Cell &a, const T &ta, const db::Cell &b, const T &tb) const
|
||||
{
|
||||
for (std::map<unsigned int, layers_type>::const_iterator i = m_connected.begin (); i != m_connected.end (); ++i) {
|
||||
db::Box ba = a.bbox (i->first);
|
||||
if (! ba.empty ()) {
|
||||
ba.transform (ta);
|
||||
for (layers_type::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
db::Box bb = b.bbox (*j);
|
||||
if (! bb.empty () && bb.transformed (tb).touches (ba)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::NetShape> (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::UnitTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::NetShape> (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::ICplxTrans &trans) const;
|
||||
|
|
@ -318,6 +371,7 @@ template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::Polyg
|
|||
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::UnitTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::ICplxTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interact<db::ICplxTrans> (const db::Cell &a, const db::ICplxTrans &ta, const db::Cell &b, const db::ICplxTrans &tb) const;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// local_cluster implementation
|
||||
|
|
@ -414,6 +468,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>
|
||||
|
|
@ -543,15 +610,7 @@ local_cluster<T>::interacts (const local_cluster<T> &other, const db::ICplxTrans
|
|||
return false;
|
||||
}
|
||||
|
||||
bool any = false;
|
||||
|
||||
for (std::set<unsigned int>::const_iterator i = ll1.begin (); i != ll1.end () && !any; ++i) {
|
||||
db::Connectivity::layer_iterator je = conn.end_connected (*i);
|
||||
for (db::Connectivity::layer_iterator j = conn.begin_connected (*i); j != je && !any; ++j) {
|
||||
any = (ll2.find (*j) != ll2.end ());
|
||||
}
|
||||
}
|
||||
if (! any) {
|
||||
if (! conn.interacts (ll1, ll2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -786,6 +845,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 +1283,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 +1378,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)
|
||||
|
|
@ -1339,11 +1438,37 @@ public:
|
|||
* @brief Constructor
|
||||
*/
|
||||
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, typename hier_clusters<T>::instance_interaction_cache_type *instance_interaction_cache)
|
||||
: mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn), mp_breakout_cells (breakout_cells), mp_instance_interaction_cache (instance_interaction_cache)
|
||||
: mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn), mp_breakout_cells (breakout_cells), m_cluster_cache_misses (0), m_cluster_cache_hits (0), mp_instance_interaction_cache (instance_interaction_cache)
|
||||
{
|
||||
mp_cell_clusters = &cell_clusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the cache size
|
||||
*/
|
||||
size_t cluster_cache_size () const
|
||||
{
|
||||
db::MemStatisticsSimple ms;
|
||||
ms << m_interaction_cache_for_clusters;
|
||||
return ms.used ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the cache hits
|
||||
*/
|
||||
size_t cluster_cache_hits () const
|
||||
{
|
||||
return m_cluster_cache_hits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the cache misses
|
||||
*/
|
||||
size_t cluster_cache_misses () const
|
||||
{
|
||||
return m_cluster_cache_misses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receiver main event for instance-to-instance interactions
|
||||
*/
|
||||
|
|
@ -1429,32 +1554,6 @@ public:
|
|||
void finalize (bool) { }
|
||||
|
||||
private:
|
||||
struct InteractionKeyForClustersType
|
||||
: public InstanceToInstanceInteraction
|
||||
{
|
||||
InteractionKeyForClustersType (db::cell_index_type _ci1, db::cell_index_type _ci2, const db::ICplxTrans &_t1, const db::ICplxTrans &_t21, const box_type &_box)
|
||||
: InstanceToInstanceInteraction (_ci1, 0, _ci2, 0, _t1, _t21), box (_box)
|
||||
{ }
|
||||
|
||||
bool operator== (const InteractionKeyForClustersType &other) const
|
||||
{
|
||||
return InstanceToInstanceInteraction::operator== (other) && box == other.box;
|
||||
}
|
||||
|
||||
bool operator< (const InteractionKeyForClustersType &other) const
|
||||
{
|
||||
if (! InstanceToInstanceInteraction::operator== (other)) {
|
||||
return InstanceToInstanceInteraction::operator< (other);
|
||||
}
|
||||
if (box != other.box) {
|
||||
return box < other.box;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
box_type box;
|
||||
};
|
||||
|
||||
const db::Layout *mp_layout;
|
||||
const db::Cell *mp_cell;
|
||||
db::connected_clusters<T> *mp_cell_clusters;
|
||||
|
|
@ -1466,8 +1565,9 @@ private:
|
|||
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
||||
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;
|
||||
instance_interaction_cache<interaction_key_for_clusters<box_type>, std::list<std::pair<size_t, size_t> > > m_interaction_cache_for_clusters;
|
||||
size_t m_cluster_cache_misses, m_cluster_cache_hits;
|
||||
typename hier_clusters<T>::instance_interaction_cache_type *mp_instance_interaction_cache;
|
||||
|
||||
/**
|
||||
* @brief Investigate a pair of instances
|
||||
|
|
@ -1488,7 +1588,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;
|
||||
|
|
@ -1506,13 +1606,21 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
// gross shortcut: the cells do no comprise a constallation which will ever interact
|
||||
if (! mp_conn->interact (mp_layout->cell (i1.cell_index ()), mp_layout->cell (i2.cell_index ()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
InstanceToInstanceInteraction ii_key;
|
||||
db::ICplxTrans i1t, i2t;
|
||||
bool fill_cache = false;
|
||||
|
||||
// Cache is only used for single instances, non-iterated, simple or regular arrays.
|
||||
if ((! i1element.at_end () || i1.size () == 1 || ! i1.is_iterated_array ()) &&
|
||||
(! i2element.at_end () || i2.size () == 1 || ! i2.is_iterated_array ())) {
|
||||
size_t n1 = i1element.at_end () ? i1.size () : 1;
|
||||
size_t n2 = i2element.at_end () ? i2.size () : 1;
|
||||
|
||||
// Cache is only used for single instances or simple and regular arrays.
|
||||
if ((n1 == 1 || ! i1.is_iterated_array ()) &&
|
||||
(n2 == 1 || ! i2.is_iterated_array ())) {
|
||||
|
||||
i1t = i1element.at_end () ? i1.complex_trans () : i1.complex_trans (*i1element);
|
||||
db::ICplxTrans tt1 = t1 * i1t;
|
||||
|
|
@ -1521,16 +1629,16 @@ private:
|
|||
db::ICplxTrans tt2 = t2 * i2t;
|
||||
|
||||
db::ICplxTrans cache_norm = tt1.inverted ();
|
||||
ii_key = InstanceToInstanceInteraction (i1.cell_index (), (! i1element.at_end () || i1.size () == 1) ? 0 : i1.cell_inst ().delegate (),
|
||||
i2.cell_index (), (! i2element.at_end () || i2.size () == 1) ? 0 : i2.cell_inst ().delegate (),
|
||||
ii_key = InstanceToInstanceInteraction ((! i1element.at_end () || i1.size () == 1) ? 0 : i1.cell_inst ().delegate (),
|
||||
(! 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 (i1.cell_index (), i2.cell_index (), 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);
|
||||
|
|
@ -1542,10 +1650,35 @@ private:
|
|||
|
||||
}
|
||||
|
||||
// avoid caching few-to-many interactions as this typically does not contribute anything
|
||||
fill_cache = true;
|
||||
|
||||
}
|
||||
|
||||
// shortcut: if the instances cannot interact because their bounding boxes do no comprise a valid constellation,
|
||||
// reject the pair
|
||||
|
||||
bool any = false;
|
||||
for (db::Connectivity::layer_iterator la = mp_conn->begin_layers (); la != mp_conn->end_layers () && ! any; ++la) {
|
||||
db::box_convert<db::CellInst, true> bca (*mp_layout, *la);
|
||||
box_type bb1 = i1.cell_inst ().bbox (bca).transformed (t1);
|
||||
if (! bb1.empty ()) {
|
||||
db::Connectivity::layer_iterator lbe = mp_conn->end_connected (*la);
|
||||
for (db::Connectivity::layer_iterator lb = mp_conn->begin_connected (*la); lb != lbe && ! any; ++lb) {
|
||||
db::box_convert<db::CellInst, true> bcb (*mp_layout, *lb);
|
||||
box_type bb2 = i2.cell_inst ().bbox (bcb).transformed (t2);
|
||||
any = bb1.touches (bb2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! any) {
|
||||
if (fill_cache) {
|
||||
mp_instance_interaction_cache->insert (i1.cell_index (), i2.cell_index (), ii_key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// array interactions
|
||||
|
||||
db::ICplxTrans t1i = t1.inverted ();
|
||||
|
|
@ -1572,9 +1705,9 @@ private:
|
|||
box_type common12 = ib1 & ib2 & common;
|
||||
if (! common12.empty ()) {
|
||||
|
||||
const std::vector<std::pair<size_t, size_t> > &i2i_interactions = compute_instance_interactions (common12, i1.cell_index (), tt1, i2.cell_index (), tt2);
|
||||
const std::list<std::pair<size_t, size_t> > &i2i_interactions = compute_instance_interactions (common12, i1.cell_index (), tt1, i2.cell_index (), tt2);
|
||||
|
||||
for (std::vector<std::pair<size_t, size_t> >::const_iterator ii = i2i_interactions.begin (); ii != i2i_interactions.end (); ++ii) {
|
||||
for (std::list<std::pair<size_t, size_t> >::const_iterator ii = i2i_interactions.begin (); ii != i2i_interactions.end (); ++ii) {
|
||||
ClusterInstance k1 (ii->first, i1.cell_index (), i1t, i1.prop_id ());
|
||||
ClusterInstance k2 (ii->second, i2.cell_index (), i2t, i2.prop_id ());
|
||||
interacting_clusters.push_back (std::make_pair (k1, k2));
|
||||
|
|
@ -1596,6 +1729,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 +1753,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;
|
||||
}
|
||||
|
|
@ -1644,7 +1772,7 @@ private:
|
|||
// return the list of unique interactions
|
||||
interacting_clusters.insert (interacting_clusters.end (), sorted_interactions.begin (), sorted_interactions.end ());
|
||||
|
||||
if (fill_cache) {
|
||||
if (fill_cache && sorted_interactions.size () < instance_to_instance_cache_set_size_threshold) {
|
||||
|
||||
// normalize transformations for cache
|
||||
db::ICplxTrans i1ti = i1t.inverted (), i2ti = i2t.inverted ();
|
||||
|
|
@ -1653,7 +1781,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 (i1.cell_index (), i2.cell_index (), ii_key);
|
||||
cached.insert (cached.end (), sorted_interactions.begin (), sorted_interactions.end ());
|
||||
|
||||
}
|
||||
|
|
@ -1662,13 +1790,13 @@ private:
|
|||
/**
|
||||
* @brief Computes a list of interacting clusters for two instances
|
||||
*/
|
||||
const std::vector<std::pair<size_t, size_t> > &
|
||||
const std::list<std::pair<size_t, size_t> > &
|
||||
compute_instance_interactions (const box_type &common,
|
||||
db::cell_index_type ci1, const db::ICplxTrans &t1,
|
||||
db::cell_index_type ci2, const db::ICplxTrans &t2)
|
||||
{
|
||||
if (is_breakout_cell (mp_breakout_cells, ci1) || is_breakout_cell (mp_breakout_cells, ci2)) {
|
||||
static const std::vector<std::pair<size_t, size_t> > empty;
|
||||
static const std::list<std::pair<size_t, size_t> > empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
|
@ -1678,12 +1806,12 @@ private:
|
|||
|
||||
box_type common2 = common.transformed (t2i);
|
||||
|
||||
InteractionKeyForClustersType ikey (ci1, ci2, t1i, t21, common2);
|
||||
interaction_key_for_clusters<box_type> ikey (t1i, t21, common2);
|
||||
|
||||
typename std::map<InteractionKeyForClustersType, std::vector<std::pair<size_t, size_t> > >::const_iterator ici = m_interaction_cache_for_clusters.find (ikey);
|
||||
if (ici != m_interaction_cache_for_clusters.end ()) {
|
||||
const std::list<std::pair<size_t, size_t> > *ici = m_interaction_cache_for_clusters.find (ci1, ci2, ikey);
|
||||
if (ici) {
|
||||
|
||||
return ici->second;
|
||||
return *ici;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1692,7 +1820,7 @@ private:
|
|||
const db::local_clusters<T> &cl1 = mp_tree->clusters_per_cell (ci1);
|
||||
const db::local_clusters<T> &cl2 = mp_tree->clusters_per_cell (ci2);
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > &new_interactions = m_interaction_cache_for_clusters [ikey];
|
||||
std::list<std::pair<size_t, size_t> > &new_interactions = m_interaction_cache_for_clusters.insert (ci1, ci2, ikey);
|
||||
db::ICplxTrans t12 = t2i * t1;
|
||||
|
||||
for (typename db::local_clusters<T>::touching_iterator i = cl1.begin_touching (common2.transformed (t21)); ! i.at_end (); ++i) {
|
||||
|
|
@ -1758,8 +1886,8 @@ private:
|
|||
cluster_instance_pair_list_type interacting_clusters;
|
||||
|
||||
box_type common = (ib & ib2);
|
||||
const std::vector<std::pair<size_t, size_t> > &i2i_interactions = compute_instance_interactions (common, i.cell_index (), tt, i.cell_index (), tt2);
|
||||
for (std::vector<std::pair<size_t, size_t> >::const_iterator ii = i2i_interactions.begin (); ii != i2i_interactions.end (); ++ii) {
|
||||
const std::list<std::pair<size_t, size_t> > &i2i_interactions = compute_instance_interactions (common, i.cell_index (), tt, i.cell_index (), tt2);
|
||||
for (std::list<std::pair<size_t, size_t> >::const_iterator ii = i2i_interactions.begin (); ii != i2i_interactions.end (); ++ii) {
|
||||
ClusterInstance k1 (ii->first, i.cell_index (), tt, i.prop_id ());
|
||||
ClusterInstance k2 (ii->second, i.cell_index (), tt2, i.prop_id ());
|
||||
interacting_clusters.push_back (std::make_pair (k1, k2));
|
||||
|
|
@ -2002,6 +2130,7 @@ private:
|
|||
|
||||
// for instance-to-instance interactions the number of connections is more important for the
|
||||
// cost of the join operation: make the one with more connections the target
|
||||
// TODO: this will be SLOW for STL's not providing a fast size()
|
||||
if (mp_cell_clusters->connections_for_cluster (x1).size () < mp_cell_clusters->connections_for_cluster (x2).size ()) {
|
||||
std::swap (x1, x2);
|
||||
}
|
||||
|
|
@ -2187,6 +2316,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 () >= m_base_verbosity + 20) {
|
||||
tl::info << "Cluster build cache statistics (instance to instance cache): size=" << instance_interaction_cache.size () << ", hits=" << instance_interaction_cache.hits () << ", misses=" << instance_interaction_cache.misses ();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
@ -2378,6 +2511,11 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
|
|||
|
||||
// join local clusters which got connected by child clusters
|
||||
rec->finish_cluster_to_instance_interactions ();
|
||||
|
||||
if (tl::verbosity () >= m_base_verbosity + 20) {
|
||||
tl::info << "Cluster build cache statistics (instance to shape cache): size=" << rec->cluster_cache_size () << ", hits=" << rec->cluster_cache_hits () << ", misses=" << rec->cluster_cache_misses ();
|
||||
}
|
||||
|
||||
rec.reset (0);
|
||||
|
||||
// finally connect global nets
|
||||
|
|
|
|||
|
|
@ -187,6 +187,22 @@ public:
|
|||
return interacts (a, la, b, lb, UnitTrans ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true, if two sets of layers interact
|
||||
*/
|
||||
bool interacts (const std::set<unsigned int> &la, const std::set<unsigned int> &lb) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if two cells basically (without considering transformation) interact
|
||||
*/
|
||||
bool interact (const db::Cell &a, const db::Cell &b) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if two cells with the given transformations interact
|
||||
*/
|
||||
template <class T>
|
||||
bool interact (const db::Cell &a, const T &ta, const db::Cell &b, const T &tb) const;
|
||||
|
||||
private:
|
||||
layers_type m_all_layers;
|
||||
std::map<unsigned int, layers_type> m_connected;
|
||||
|
|
@ -365,6 +381,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 +413,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 +563,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 +587,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
|
||||
*/
|
||||
|
|
@ -760,10 +812,10 @@ inline bool less_array_delegates (const db::ArrayBase *a, const db::ArrayBase *b
|
|||
/**
|
||||
* @brief A helper struct to describe a pair of cell instances with a specific relative transformation
|
||||
*/
|
||||
struct InstanceToInstanceInteraction
|
||||
struct DB_PUBLIC InstanceToInstanceInteraction
|
||||
{
|
||||
InstanceToInstanceInteraction (db::cell_index_type _ci1, const db::ArrayBase *_array1, db::cell_index_type _ci2, const db::ArrayBase *_array2, const db::ICplxTrans &_tn, const db::ICplxTrans &_t21)
|
||||
: ci1 (_ci1), ci2 (_ci2), array1 (0), array2 (0), t21 (_t21)
|
||||
InstanceToInstanceInteraction (const db::ArrayBase *_array1, const db::ArrayBase *_array2, const db::ICplxTrans &_tn, const db::ICplxTrans &_t21)
|
||||
: array1 (0), array2 (0), t21 (_t21)
|
||||
{
|
||||
if (_array1) {
|
||||
array1 = _array1->basic_clone ();
|
||||
|
|
@ -777,14 +829,13 @@ struct InstanceToInstanceInteraction
|
|||
}
|
||||
|
||||
InstanceToInstanceInteraction ()
|
||||
: ci1 (0), ci2 (0), array1 (0), array2 (0)
|
||||
: array1 (0), array2 (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
InstanceToInstanceInteraction (const InstanceToInstanceInteraction &other)
|
||||
: ci1 (other.ci1), ci2 (other.ci2),
|
||||
array1 (other.array1 ? other.array1->basic_clone () : 0),
|
||||
: array1 (other.array1 ? other.array1->basic_clone () : 0),
|
||||
array2 (other.array2 ? other.array2->basic_clone () : 0),
|
||||
t21 (other.t21)
|
||||
{
|
||||
|
|
@ -795,9 +846,6 @@ struct InstanceToInstanceInteraction
|
|||
{
|
||||
if (this != &other) {
|
||||
|
||||
ci1 = other.ci1;
|
||||
ci2 = other.ci2;
|
||||
|
||||
if (array1) {
|
||||
delete array1;
|
||||
}
|
||||
|
|
@ -830,19 +878,13 @@ struct InstanceToInstanceInteraction
|
|||
|
||||
bool operator== (const InstanceToInstanceInteraction &other) const
|
||||
{
|
||||
return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21) &&
|
||||
return t21.equal (other.t21) &&
|
||||
equal_array_delegates (array1, other.array1) &&
|
||||
equal_array_delegates (array2, other.array2);
|
||||
}
|
||||
|
||||
bool operator< (const InstanceToInstanceInteraction &other) const
|
||||
{
|
||||
if (ci1 != other.ci1) {
|
||||
return ci1 < other.ci1;
|
||||
}
|
||||
if (ci2 != other.ci2) {
|
||||
return ci2 < other.ci2;
|
||||
}
|
||||
if (! t21.equal (other.t21)) {
|
||||
return t21.less (other.t21);
|
||||
}
|
||||
|
|
@ -854,12 +896,109 @@ struct InstanceToInstanceInteraction
|
|||
return less_array_delegates (array2, other.array2);
|
||||
}
|
||||
|
||||
db::cell_index_type ci1, ci2;
|
||||
db::ArrayBase *array1, *array2;
|
||||
db::ICplxTrans t21;
|
||||
};
|
||||
|
||||
typedef std::map<InstanceToInstanceInteraction, cluster_instance_pair_list_type> instance_interaction_cache_type;
|
||||
template <class Box>
|
||||
struct DB_PUBLIC_TEMPLATE interaction_key_for_clusters
|
||||
: public InstanceToInstanceInteraction
|
||||
{
|
||||
interaction_key_for_clusters (const db::ICplxTrans &_t1, const db::ICplxTrans &_t21, const Box &_box)
|
||||
: InstanceToInstanceInteraction (0, 0, _t1, _t21), box (_box)
|
||||
{ }
|
||||
|
||||
bool operator== (const interaction_key_for_clusters &other) const
|
||||
{
|
||||
return InstanceToInstanceInteraction::operator== (other) && box == other.box;
|
||||
}
|
||||
|
||||
bool operator< (const interaction_key_for_clusters &other) const
|
||||
{
|
||||
if (! InstanceToInstanceInteraction::operator== (other)) {
|
||||
return InstanceToInstanceInteraction::operator< (other);
|
||||
}
|
||||
if (box != other.box) {
|
||||
return box < other.box;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Box box;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An object representing the instance interaction cache
|
||||
*/
|
||||
template <class Key, class Value>
|
||||
class DB_PUBLIC_TEMPLATE instance_interaction_cache
|
||||
{
|
||||
public:
|
||||
instance_interaction_cache ()
|
||||
: m_hits (0), m_misses (0)
|
||||
{ }
|
||||
|
||||
size_t size () const
|
||||
{
|
||||
MemStatisticsSimple ms;
|
||||
ms << m_map;
|
||||
return ms.used ();
|
||||
}
|
||||
|
||||
size_t hits () const
|
||||
{
|
||||
return m_hits;
|
||||
}
|
||||
|
||||
size_t misses () const
|
||||
{
|
||||
return m_misses;
|
||||
}
|
||||
|
||||
const Value *find (db::cell_index_type ci1, db::cell_index_type ci2, const Key &key) const
|
||||
{
|
||||
typename std::map <std::pair<db::cell_index_type, db::cell_index_type>, std::list <std::pair<Key, Value> > >::iterator i1 = m_map.find (std::make_pair (ci1, ci2));
|
||||
if (i1 == m_map.end ()) {
|
||||
++m_misses;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: the number of entries is low, so we can afford a linear search
|
||||
typename std::list <std::pair<Key, Value> >::iterator i = i1->second.begin ();
|
||||
while (i != i1->second.end () && ! (i->first == key)) {
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i == i1->second.end ()) {
|
||||
++m_misses;
|
||||
return 0;
|
||||
} else {
|
||||
// move the element to the front so the most frequently used ones are at the front
|
||||
if (i != i1->second.begin ()) {
|
||||
i1->second.splice (i1->second.begin(), i1->second, i, std::next (i));
|
||||
}
|
||||
++m_hits;
|
||||
return &i->second;
|
||||
}
|
||||
}
|
||||
|
||||
Value &insert (db::cell_index_type ci1, db::cell_index_type ci2, const Key &key)
|
||||
{
|
||||
const size_t instance_cache_variant_threshold = 20;
|
||||
|
||||
std::list <std::pair<Key, Value> > &m = m_map [std::make_pair (ci1, ci2)];
|
||||
if (m.size () >= instance_cache_variant_threshold) {
|
||||
m.pop_back ();
|
||||
}
|
||||
|
||||
m.push_front (std::make_pair (key, Value ()));
|
||||
return m.front ().second;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable size_t m_hits, m_misses;
|
||||
mutable std::map <std::pair<db::cell_index_type, db::cell_index_type>, std::list <std::pair<Key, Value> > > m_map;
|
||||
};
|
||||
|
||||
template <class T> class hier_clusters;
|
||||
template <class T> class connected_clusters;
|
||||
|
|
@ -1013,6 +1152,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 +1165,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 +1187,8 @@ 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;
|
||||
|
||||
typedef instance_interaction_cache<InstanceToInstanceInteraction, cluster_instance_pair_list_type> instance_interaction_cache_type;
|
||||
|
||||
/**
|
||||
* @brief Creates an empty set of clusters
|
||||
|
|
@ -1094,6 +1248,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -103,6 +108,45 @@ private:
|
|||
std::map<purpose_t, std::pair<size_t, size_t> > m_per_purpose;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A simple memory statistics collector
|
||||
* This collector will simply add the size required
|
||||
*/
|
||||
class DB_PUBLIC MemStatisticsSimple
|
||||
: public MemStatistics
|
||||
{
|
||||
public:
|
||||
MemStatisticsSimple ()
|
||||
: m_size (0), m_used (0)
|
||||
{ }
|
||||
|
||||
size_t size () const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_t used () const
|
||||
{
|
||||
return m_used;
|
||||
}
|
||||
|
||||
virtual void add (const std::type_info & /*ti*/, void * /*ptr*/, size_t size, size_t used, void * /*parent*/, purpose_t /*purpose*/, int /*cat*/)
|
||||
{
|
||||
m_size += size;
|
||||
m_used += used;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
MemStatisticsSimple &operator<< (const T &x)
|
||||
{
|
||||
mem_stat (this, None, 0, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_size, m_used;
|
||||
};
|
||||
|
||||
// Some standard templates to collect the information
|
||||
template <class X>
|
||||
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const X &x, bool no_self = false, void *parent = 0)
|
||||
|
|
@ -120,7 +164,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 +181,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 +195,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 +211,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 +281,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue