mirror of https://github.com/KLayout/klayout.git
WIP: added ref counting for deep shape layers and layouts
This commit is contained in:
parent
fc729fc830
commit
712a390f52
|
|
@ -41,18 +41,42 @@ DeepLayer::DeepLayer ()
|
|||
DeepLayer::DeepLayer (const DeepLayer &x)
|
||||
: mp_store (x.mp_store), m_layout (x.m_layout), m_layer (x.m_layer)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
if (mp_store.get ()) {
|
||||
mp_store->add_ref (m_layout, m_layer);
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer::DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int layer)
|
||||
: mp_store (store), m_layout (layout), m_layer (layer)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
if (store) {
|
||||
store->add_ref (layout, layer);
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer &DeepLayer::operator= (const DeepLayer &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (mp_store.get ()) {
|
||||
mp_store->remove_ref (m_layout, m_layer);
|
||||
}
|
||||
mp_store = other.mp_store;
|
||||
m_layout = other.m_layout;
|
||||
m_layer = other.m_layer;
|
||||
if (mp_store.get ()) {
|
||||
mp_store->add_ref (m_layout, m_layer);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DeepLayer::~DeepLayer ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
if (mp_store.get ()) {
|
||||
mp_store->remove_ref (m_layout, m_layer);
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer
|
||||
|
|
@ -121,6 +145,35 @@ DeepLayer::check_dss () const
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
struct DeepShapeStore::LayoutHolder
|
||||
{
|
||||
LayoutHolder ()
|
||||
: refs (0), layout (), builder (&layout)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void add_layer_ref (unsigned int layer)
|
||||
{
|
||||
layer_refs[layer] += 1;
|
||||
}
|
||||
|
||||
void remove_layer_ref (unsigned int layer)
|
||||
{
|
||||
if ((layer_refs[layer] -= 1) <= 0) {
|
||||
layout.clear_layer (layer);
|
||||
layer_refs.erase (layer);
|
||||
}
|
||||
}
|
||||
|
||||
int refs;
|
||||
db::Layout layout;
|
||||
db::HierarchyBuilder builder;
|
||||
std::map<unsigned int, int> layer_refs;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
static size_t s_instance_count = 0;
|
||||
|
||||
DeepShapeStore::DeepShapeStore ()
|
||||
|
|
@ -132,6 +185,28 @@ DeepShapeStore::DeepShapeStore ()
|
|||
DeepShapeStore::~DeepShapeStore ()
|
||||
{
|
||||
--s_instance_count;
|
||||
|
||||
for (std::vector<LayoutHolder *>::iterator h = m_layouts.begin (); h != m_layouts.end (); ++h) {
|
||||
delete *h;
|
||||
}
|
||||
m_layouts.clear ();
|
||||
}
|
||||
|
||||
bool DeepShapeStore::is_valid_layout_index (unsigned int n) const
|
||||
{
|
||||
return (n < (unsigned int) m_layouts.size () && m_layouts[n] != 0);
|
||||
}
|
||||
|
||||
const db::Layout *DeepShapeStore::const_layout (unsigned int n) const
|
||||
{
|
||||
tl_assert (is_valid_layout_index (n));
|
||||
return &(m_layouts [n]->layout);
|
||||
}
|
||||
|
||||
db::Layout *DeepShapeStore::layout (unsigned int n)
|
||||
{
|
||||
tl_assert (is_valid_layout_index (n));
|
||||
return &(m_layouts [n]->layout);
|
||||
}
|
||||
|
||||
size_t DeepShapeStore::instance_count ()
|
||||
|
|
@ -144,35 +219,55 @@ void DeepShapeStore::set_threads (int n)
|
|||
m_threads = n;
|
||||
}
|
||||
|
||||
void DeepShapeStore::add_ref (unsigned int layout, unsigned int layer)
|
||||
{
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
|
||||
tl_assert (layout < (unsigned int) m_layouts.size () && m_layouts[layout] != 0);
|
||||
|
||||
m_layouts[layout]->refs += 1;
|
||||
m_layouts[layout]->add_layer_ref (layer);
|
||||
}
|
||||
|
||||
void DeepShapeStore::remove_ref (unsigned int layout, unsigned int layer)
|
||||
{
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
|
||||
tl_assert (layout < (unsigned int) m_layouts.size () && m_layouts[layout] != 0);
|
||||
|
||||
m_layouts[layout]->remove_layer_ref (layer);
|
||||
|
||||
if ((m_layouts[layout]->refs -= 1) <= 0) {
|
||||
delete m_layouts[layout];
|
||||
m_layouts[layout] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
|
||||
{
|
||||
unsigned int layout_index = 0;
|
||||
unsigned int layer_index = 0;
|
||||
|
||||
layout_map_type::iterator l = m_layout_map.find (si);
|
||||
if (l == m_layout_map.end ()) {
|
||||
|
||||
layout_index = (unsigned int) m_layouts.size ();
|
||||
|
||||
m_layouts.push_back (new db::Layout ());
|
||||
m_layouts.back ().dbu (si.layout ()->dbu ());
|
||||
layer_index = m_layouts.back ().insert_layer ();
|
||||
|
||||
m_builders.push_back (new db::HierarchyBuilder (&m_layouts.back (), layer_index));
|
||||
m_layouts.push_back (new LayoutHolder ());
|
||||
m_layouts.back ()->layout.dbu (si.layout ()->dbu ());
|
||||
|
||||
m_layout_map[si] = layout_index;
|
||||
|
||||
} else {
|
||||
|
||||
layout_index = l->second;
|
||||
layer_index = m_layouts[layout_index].insert_layer ();
|
||||
|
||||
m_builders[layout_index].set_target_layer (layer_index);
|
||||
|
||||
}
|
||||
|
||||
unsigned int layer_index = m_layouts[layout_index]->layout.insert_layer ();
|
||||
m_layouts[layout_index]->builder.set_target_layer (layer_index);
|
||||
|
||||
// The chain of operators for producing clipped and reduced polygon references
|
||||
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& m_layouts[layout_index]);
|
||||
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& m_layouts[layout_index]->layout);
|
||||
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
|
||||
db::ClippingHierarchyBuilderShapeReceiver clip (&red);
|
||||
|
||||
|
|
@ -181,12 +276,12 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
|
||||
tl::SelfTimer timer (tl::to_string (tr ("Building working hierarchy")));
|
||||
|
||||
m_builders[layout_index].set_shape_receiver (&clip);
|
||||
db::RecursiveShapeIterator (si).push (& m_builders[layout_index]);
|
||||
m_builders[layout_index].set_shape_receiver (0);
|
||||
m_layouts[layout_index]->builder.set_shape_receiver (&clip);
|
||||
db::RecursiveShapeIterator (si).push (& m_layouts[layout_index]->builder);
|
||||
m_layouts[layout_index]->builder.set_shape_receiver (0);
|
||||
|
||||
} catch (...) {
|
||||
m_builders[layout_index].set_shape_receiver (0);
|
||||
m_layouts[layout_index]->builder.set_shape_receiver (0);
|
||||
throw;
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +299,7 @@ DeepShapeStore::insert (const DeepLayer &deep_layer, db::Layout *into_layout, db
|
|||
|
||||
db::cell_index_type source_top = *source_layout->begin_top_down();
|
||||
|
||||
db::HierarchyBuilder &original_builder = m_builders [deep_layer.layout_index ()];
|
||||
db::HierarchyBuilder &original_builder = m_layouts [deep_layer.layout_index ()]->builder;
|
||||
|
||||
// derive a cell mapping for source to target. We employ a
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "tlObject.h"
|
||||
#include "tlStableVector.h"
|
||||
#include "tlThreads.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbHierarchyBuilder.h"
|
||||
|
|
@ -197,7 +198,7 @@ public:
|
|||
DeepLayer create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
|
||||
/**
|
||||
* @brief Inserts the deep layer's into some target layout
|
||||
* @brief Inserts the deep layer's shapes into some target layout
|
||||
*/
|
||||
void insert (const DeepLayer &layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer);
|
||||
|
||||
|
|
@ -206,6 +207,24 @@ public:
|
|||
*/
|
||||
static size_t instance_count ();
|
||||
|
||||
/**
|
||||
* @brief Gets the nth layout (const version)
|
||||
*/
|
||||
const db::Layout *const_layout (unsigned int n) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of layouts
|
||||
*/
|
||||
unsigned int layouts () const
|
||||
{
|
||||
return (unsigned int) m_layouts.size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the given index is a valid layout index
|
||||
*/
|
||||
bool is_valid_layout_index (unsigned int n) const;
|
||||
|
||||
/**
|
||||
* @brief The deep shape store also keeps the number of threads to allocate for the hierarchical processor
|
||||
*
|
||||
|
|
@ -224,10 +243,12 @@ public:
|
|||
private:
|
||||
friend class DeepLayer;
|
||||
|
||||
db::Layout *layout (unsigned int n)
|
||||
{
|
||||
return &m_layouts [n];
|
||||
}
|
||||
struct LayoutHolder;
|
||||
|
||||
db::Layout *layout (unsigned int n);
|
||||
|
||||
void add_ref (unsigned int layout, unsigned int layer);
|
||||
void remove_ref (unsigned int layout, unsigned int layer);
|
||||
|
||||
typedef std::map<db::RecursiveShapeIterator, unsigned int, RecursiveShapeIteratorCompareForTargetHierarchy> layout_map_type;
|
||||
|
||||
|
|
@ -235,10 +256,10 @@ private:
|
|||
DeepShapeStore (const DeepShapeStore &);
|
||||
DeepShapeStore &operator= (const DeepShapeStore &);
|
||||
|
||||
tl::stable_vector<db::Layout> m_layouts;
|
||||
tl::stable_vector<db::HierarchyBuilder> m_builders;
|
||||
std::vector<LayoutHolder *> m_layouts;
|
||||
layout_map_type m_layout_map;
|
||||
int m_threads;
|
||||
tl::Mutex m_lock;
|
||||
|
||||
struct DeliveryMappingCacheKey
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,151 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
db::DeepShapeStore store;
|
||||
db::Layout layout;
|
||||
|
||||
unsigned int l1 = layout.insert_layer ();
|
||||
unsigned int l2 = layout.insert_layer ();
|
||||
db::cell_index_type c1 = layout.add_cell ("C1");
|
||||
db::cell_index_type c2 = layout.add_cell ("C2");
|
||||
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 0);
|
||||
|
||||
db::DeepLayer dl1 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1));
|
||||
db::DeepLayer dl2 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l2));
|
||||
|
||||
EXPECT_EQ (dl1.layer (), l1);
|
||||
EXPECT_EQ (dl2.layer (), l2);
|
||||
EXPECT_EQ (dl1.layout (), dl2.layout ());
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 1);
|
||||
|
||||
db::DeepLayer dl3 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c2), l1));
|
||||
EXPECT_EQ (dl3.layer (), l1);
|
||||
EXPECT_NE (dl1.layout (), dl3.layout ());
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 2);
|
||||
|
||||
db::DeepLayer dl4 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1, db::Box (0, 1, 2, 3)));
|
||||
db::DeepLayer dl5 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l2, db::Box (0, 1, 2, 3)));
|
||||
EXPECT_EQ (dl4.layer (), l1);
|
||||
EXPECT_EQ (dl5.layer (), l1); // not l2, because it's a new layout
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 4);
|
||||
|
||||
db::DeepLayer dl6 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1, db::Box (0, 1, 2, 3)));
|
||||
EXPECT_EQ (dl6.layer (), l2); // a new layer (a copy)
|
||||
EXPECT_EQ (dl6.layout (), dl4.layout ());
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 4);
|
||||
}
|
||||
|
||||
static size_t shapes_in_top (const db::Layout *layout, unsigned int layer)
|
||||
{
|
||||
const db::Cell &top = layout->cell (*layout->begin_top_down ());
|
||||
return top.shapes (layer).size ();
|
||||
}
|
||||
|
||||
TEST(2_RefCounting)
|
||||
{
|
||||
db::DeepShapeStore store;
|
||||
db::Layout layout;
|
||||
|
||||
unsigned int l1 = layout.insert_layer ();
|
||||
unsigned int l2 = layout.insert_layer ();
|
||||
db::cell_index_type c1 = layout.add_cell ("C1");
|
||||
db::cell_index_type c2 = layout.add_cell ("C2");
|
||||
layout.cell (c1).shapes (l1).insert (db::Box (0, 1, 2, 3));
|
||||
layout.cell (c1).shapes (l2).insert (db::Box (0, 1, 2, 3));
|
||||
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 0);
|
||||
|
||||
db::DeepLayer dl1 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1));
|
||||
db::DeepLayer dl2 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l2));
|
||||
db::DeepLayer dl3 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c2), l1));
|
||||
db::DeepLayer dl4 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1, db::Box (0, 1, 2, 3)));
|
||||
db::DeepLayer dl5 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l2, db::Box (0, 1, 2, 3)));
|
||||
db::DeepLayer dl6 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1, db::Box (0, 1, 2, 3)));
|
||||
|
||||
EXPECT_EQ (store.layouts (), (unsigned int) 4);
|
||||
|
||||
unsigned int lyi1 = dl1.layout_index ();
|
||||
unsigned int lyi2 = dl2.layout_index ();
|
||||
unsigned int lyi3 = dl3.layout_index ();
|
||||
unsigned int lyi4 = dl4.layout_index ();
|
||||
unsigned int lyi5 = dl5.layout_index ();
|
||||
unsigned int lyi6 = dl6.layout_index ();
|
||||
|
||||
EXPECT_EQ (lyi1, lyi2);
|
||||
EXPECT_NE (lyi3, lyi2);
|
||||
EXPECT_NE (lyi5, lyi4);
|
||||
EXPECT_NE (lyi5, lyi3);
|
||||
EXPECT_EQ (lyi6, lyi4);
|
||||
|
||||
EXPECT_EQ (dl1.layer (), l1);
|
||||
EXPECT_EQ (dl2.layer (), l2);
|
||||
EXPECT_EQ (dl4.layer (), l1);
|
||||
EXPECT_EQ (dl6.layer (), l2);
|
||||
|
||||
// dl1 and dl2 share the same layout, but not the same layer
|
||||
// dl4 and dl6 share the same layout, but not the same layer
|
||||
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi6), true);
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi5), true);
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi3), true);
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi1), true);
|
||||
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi6), l2), size_t (1));
|
||||
dl6 = db::DeepLayer ();
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi6), l2), size_t (0));
|
||||
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi6), l1), size_t (1));
|
||||
db::DeepLayer dl4a = dl4;
|
||||
dl4 = db::DeepLayer ();
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi6), l1), size_t (1));
|
||||
dl4a = db::DeepLayer ();
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi6), false);
|
||||
|
||||
dl3 = db::DeepLayer ();
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi3), false);
|
||||
|
||||
{
|
||||
db::DeepLayer dl5a = dl5;
|
||||
db::DeepLayer dl5b = dl5a;
|
||||
dl5 = db::DeepLayer ();
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi5), true);
|
||||
}
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi5), false);
|
||||
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi1), l1), size_t (1));
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi1), l2), size_t (1));
|
||||
|
||||
dl1 = db::DeepLayer ();
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi1), l1), size_t (0));
|
||||
EXPECT_EQ (shapes_in_top (store.const_layout (lyi1), l2), size_t (1));
|
||||
|
||||
dl2 = db::DeepLayer ();
|
||||
EXPECT_EQ (store.is_valid_layout_index (lyi1), false);
|
||||
}
|
||||
|
|
@ -56,7 +56,8 @@ SOURCES = \
|
|||
dbHierarchyBuilderTests.cc \
|
||||
dbRecursiveShapeIteratorTests.cc \
|
||||
dbHierProcessorTests.cc \
|
||||
dbDeepRegionTests.cc
|
||||
dbDeepRegionTests.cc \
|
||||
dbDeepShapeStoreTests.cc
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||
|
|
|
|||
Loading…
Reference in New Issue