WIP: added ref counting for deep shape layers and layouts

This commit is contained in:
Matthias Koefferlein 2018-11-21 00:17:14 +01:00
parent fc729fc830
commit 712a390f52
4 changed files with 294 additions and 26 deletions

View File

@ -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

View File

@ -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
{

View File

@ -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);
}

View File

@ -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