From d244d5aac66cee70c1e3e166d29a5217490770fd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 1 Nov 2021 13:48:47 +0100 Subject: [PATCH] Debugging plus enhancments Basic change: DeepShapeStore+CellMapping uses (new) hier_generation_id of Layout to figure out if the hierarchy has changed and the cache needs update. --- src/db/db/dbCellMapping.cc | 5 ++++ src/db/db/dbCellMapping.h | 5 ++++ src/db/db/dbDeepShapeStore.cc | 38 ++++++++++++--------------- src/db/db/dbDeepShapeStore.h | 41 +++++++++++++++++++++++++++--- src/db/db/dbLayout.h | 4 +-- src/db/db/dbLayoutStateModel.cc | 5 ++-- src/db/db/dbLayoutStateModel.h | 13 ++++++++++ src/db/unit_tests/dbLayoutTests.cc | 12 +++++++++ 8 files changed, 94 insertions(+), 29 deletions(-) diff --git a/src/db/db/dbCellMapping.cc b/src/db/db/dbCellMapping.cc index e945ca153..6184e740a 100644 --- a/src/db/db/dbCellMapping.cc +++ b/src/db/db/dbCellMapping.cc @@ -269,6 +269,11 @@ void CellMapping::clear () m_b2a_mapping.clear (); } +void CellMapping::swap (CellMapping &other) +{ + m_b2a_mapping.swap (other.m_b2a_mapping); +} + std::vector CellMapping::source_cells () const { std::vector s; diff --git a/src/db/db/dbCellMapping.h b/src/db/db/dbCellMapping.h index a17ef92aa..31f72be94 100644 --- a/src/db/db/dbCellMapping.h +++ b/src/db/db/dbCellMapping.h @@ -64,6 +64,11 @@ public: */ void clear (); + /** + * @brief Swaps the cell mapping with another one + */ + void swap (CellMapping &other); + /** * @brief Create a single cell mapping * diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index e62c2cfd9..89b7e84e1 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -788,7 +788,6 @@ DeepShapeStore::layout_for_iter (const db::RecursiveShapeIterator &si, const db: } db::Layout &layout = m_layouts[layout_index]->layout; - layout.hier_changed_event.add (this, &DeepShapeStore::invalidate_hier); if (si.layout ()) { layout.dbu (si.layout ()->dbu () / trans.mag ()); } @@ -812,7 +811,6 @@ void DeepShapeStore::make_layout (unsigned int layout_index, const db::Recursive m_layouts[layout_index] = new LayoutHolder (trans); db::Layout &layout = m_layouts[layout_index]->layout; - layout.hier_changed_event.add (this, &DeepShapeStore::invalidate_hier); if (si.layout ()) { layout.dbu (si.layout ()->dbu () / trans.mag ()); } @@ -935,18 +933,9 @@ DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &s return create_custom_layer (si, &refs, trans); } -void -DeepShapeStore::invalidate_hier () -{ - m_delivery_mapping_cache.clear (); - m_internal_mapping_cache.clear (); -} - void DeepShapeStore::issue_variants (unsigned int layout_index, const std::map > &var_map) { - invalidate_hier (); - db::HierarchyBuilder &builder = m_layouts [layout_index]->builder; for (std::map >::const_iterator i = var_map.begin (); i != var_map.end (); ++i) { for (std::map::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { @@ -956,19 +945,21 @@ DeepShapeStore::issue_variants (unsigned int layout_index, const std::map, db::CellMapping>::iterator cm = m_internal_mapping_cache.find (std::make_pair (from_layout_index, into_layout_index)); - if (cm == m_internal_mapping_cache.end ()) { + db::Layout &into_layout = layout (into_layout_index); + db::cell_index_type into_cell = initial_cell (into_layout_index).cell_index (); + const db::Layout &source_layout = layout (from_layout_index); + db::cell_index_type source_cell = initial_cell (from_layout_index).cell_index (); - cm = m_internal_mapping_cache.insert (std::make_pair (std::make_pair (from_layout_index, into_layout_index), db::CellMapping ())).first; + std::map, CellMappingWithGenerationIds>::iterator cm = m_internal_mapping_cache.find (std::make_pair (from_layout_index, into_layout_index)); + if (cm == m_internal_mapping_cache.end () || ! cm->second.is_valid (into_layout, source_layout)) { - db::Layout &into_layout = layout (into_layout_index); - db::cell_index_type into_cell = initial_cell (into_layout_index).cell_index (); - const db::Layout &source_layout = layout (from_layout_index); - db::cell_index_type source_cell = initial_cell (from_layout_index).cell_index (); + cm = m_internal_mapping_cache.insert (std::make_pair (std::make_pair (from_layout_index, into_layout_index), CellMappingWithGenerationIds ())).first; + cm->second.clear (); cm->second.create_from_geometry_full (into_layout, into_cell, source_layout, source_cell); + cm->second.set_generation_ids (into_layout, source_layout); } @@ -994,10 +985,11 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout DeliveryMappingCacheKey key (layout_index, tl::id_of (into_layout), into_cell); - std::map::iterator cm = m_delivery_mapping_cache.find (key); - if (cm == m_delivery_mapping_cache.end ()) { + std::map::iterator cm = m_delivery_mapping_cache.find (key); + if (cm == m_delivery_mapping_cache.end () || ! cm->second.is_valid (*into_layout, *source_layout)) { - cm = m_delivery_mapping_cache.insert (std::make_pair (key, db::CellMapping ())).first; + cm = m_delivery_mapping_cache.insert (std::make_pair (key, CellMappingWithGenerationIds ())).first; + cm->second.clear (); // collects the cell mappings we skip because they are variants (variant building or box variants) std::map cm_skipped_variants; @@ -1086,6 +1078,8 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout into_layout->delete_cells (cells_to_delete); } + cm->second.set_generation_ids (*into_layout, *source_layout); + } return cm->second; diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 990ecfb2e..877cd2bc9 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -32,6 +32,7 @@ #include "dbLayout.h" #include "dbRecursiveShapeIterator.h" #include "dbHierarchyBuilder.h" +#include "dbCellMapping.h" #include "gsiObject.h" #include @@ -291,6 +292,41 @@ struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy } }; +/** + * @brief An object holding a cell mapping with the hierarchy generation Ids of the involved layouts + */ +class DB_PUBLIC CellMappingWithGenerationIds + : public db::CellMapping +{ +public: + CellMappingWithGenerationIds () + : db::CellMapping (), m_into_generation_id (0), m_from_generation_id (0) + { + // .. nothing yet .. + } + + void swap (CellMappingWithGenerationIds &other) + { + db::CellMapping::swap (other); + std::swap (m_into_generation_id, other.m_into_generation_id); + std::swap (m_from_generation_id, other.m_from_generation_id); + } + + bool is_valid (const db::Layout &into_layout, const db::Layout &from_layout) const + { + return into_layout.hier_generation_id () == m_into_generation_id && from_layout.hier_generation_id () == m_from_generation_id; + } + + void set_generation_ids (const db::Layout &into_layout, const db::Layout &from_layout) + { + m_into_generation_id = into_layout.hier_generation_id (); + m_from_generation_id = from_layout.hier_generation_id (); + } + +private: + size_t m_into_generation_id, m_from_generation_id; +}; + /** * @brief The "deep shape store" is a working model for the hierarchical ("deep") processor * @@ -759,7 +795,6 @@ private: struct LayoutHolder; - void invalidate_hier (); void add_ref (unsigned int layout, unsigned int layer); void remove_ref (unsigned int layout, unsigned int layer); @@ -810,8 +845,8 @@ private: db::cell_index_type into_cell; }; - std::map m_delivery_mapping_cache; - std::map, db::CellMapping> m_internal_mapping_cache; + std::map m_delivery_mapping_cache; + std::map, CellMappingWithGenerationIds> m_internal_mapping_cache; }; template diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index e5ee39006..478620390 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -528,12 +528,12 @@ public: * * The editable mode will be taken from db::default_editable_mode. */ - Layout (db::Manager *manager = 0); + explicit Layout (db::Manager *manager = 0); /** * @brief Standard constructor which allows one to specify editable mode */ - Layout (bool editable, db::Manager *manager = 0); + explicit Layout (bool editable, db::Manager *manager = 0); /** * @brief The copy ctor diff --git a/src/db/db/dbLayoutStateModel.cc b/src/db/db/dbLayoutStateModel.cc index 4bcb0755f..63cc42177 100644 --- a/src/db/db/dbLayoutStateModel.cc +++ b/src/db/db/dbLayoutStateModel.cc @@ -29,13 +29,13 @@ namespace db { LayoutStateModel::LayoutStateModel (bool busy) - : m_hier_dirty (false), m_all_bboxes_dirty (false), m_busy (busy) + : m_hier_dirty (false), m_hier_generation_id (0), m_all_bboxes_dirty (false), m_busy (busy) { // .. nothing yet .. } LayoutStateModel::LayoutStateModel (const LayoutStateModel &d) - : m_hier_dirty (d.m_hier_dirty), m_bboxes_dirty (d.m_bboxes_dirty), m_all_bboxes_dirty (d.m_all_bboxes_dirty), m_busy (d.m_busy) + : m_hier_dirty (d.m_hier_dirty), m_hier_generation_id (d.m_hier_generation_id), m_bboxes_dirty (d.m_bboxes_dirty), m_all_bboxes_dirty (d.m_all_bboxes_dirty), m_busy (d.m_busy) { // .. nothing yet .. } @@ -44,6 +44,7 @@ LayoutStateModel & LayoutStateModel::operator= (const LayoutStateModel &d) { m_hier_dirty = d.m_hier_dirty; + m_hier_generation_id = d.m_hier_generation_id; m_bboxes_dirty = d.m_bboxes_dirty; m_all_bboxes_dirty = d.m_all_bboxes_dirty; m_busy = d.m_busy; diff --git a/src/db/db/dbLayoutStateModel.h b/src/db/db/dbLayoutStateModel.h index f99e04c32..20760a70d 100644 --- a/src/db/db/dbLayoutStateModel.h +++ b/src/db/db/dbLayoutStateModel.h @@ -85,6 +85,7 @@ public: */ void invalidate_hier () { + ++m_hier_generation_id; if (! m_hier_dirty || m_busy) { do_invalidate_hier (); // must be called before the hierarchy is invalidated (stopping of redraw thread requires this) m_hier_dirty = true; @@ -127,6 +128,17 @@ public: return m_hier_dirty; } + /** + * @brief Gets the hierarchy generation ID + * + * The hierarchy generation ID is a number which is incremented on every hierarchy + * change. + */ + size_t hier_generation_id () const + { + return m_hier_generation_id; + } + /** * @brief The "dirty bounding box" attribute * @@ -195,6 +207,7 @@ public: private: bool m_hier_dirty; + size_t m_hier_generation_id; std::vector m_bboxes_dirty; bool m_all_bboxes_dirty; bool m_busy; diff --git a/src/db/unit_tests/dbLayoutTests.cc b/src/db/unit_tests/dbLayoutTests.cc index c4630e5ae..303187ecb 100644 --- a/src/db/unit_tests/dbLayoutTests.cc +++ b/src/db/unit_tests/dbLayoutTests.cc @@ -261,12 +261,15 @@ TEST(2) db::cell_index_type ci; db::Cell *top; + EXPECT_EQ (g.hier_generation_id (), size_t (0)); + ci = g.add_cell ("TOP"); EXPECT_EQ (el.flags, (unsigned int) 0); EXPECT_EQ (el.bboxes_dirty, false); EXPECT_EQ (el.bboxes_all_dirty, false); EXPECT_EQ (el.hier_dirty, true); + EXPECT_EQ (g.hier_generation_id (), size_t (1)); el.reset (); top = &g.cell (ci); @@ -276,6 +279,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, false); EXPECT_EQ (el.bboxes_all_dirty, false); EXPECT_EQ (el.hier_dirty, false); // needs g.update() before being issues again + EXPECT_EQ (g.hier_generation_id (), size_t (2)); el.reset (); top->insert (db::CellInstArray (ci, db::Trans ())); @@ -284,10 +288,12 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, true); EXPECT_EQ (el.bboxes_all_dirty, true); EXPECT_EQ (el.hier_dirty, false); // needs g.update() before being issues again + EXPECT_EQ (g.hier_generation_id (), size_t (3)); g.clear (); g.update (); el.reset (); + EXPECT_EQ (g.hier_generation_id (), size_t (4)); ci = g.add_cell ("TOP"); @@ -295,6 +301,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, false); EXPECT_EQ (el.bboxes_all_dirty, false); EXPECT_EQ (el.hier_dirty, true); + EXPECT_EQ (g.hier_generation_id (), size_t (5)); el.reset (); g.update (); @@ -305,6 +312,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, false); EXPECT_EQ (el.bboxes_all_dirty, false); EXPECT_EQ (el.hier_dirty, true); // OK - see above + EXPECT_EQ (g.hier_generation_id (), size_t (6)); el.reset (); g.update (); @@ -314,6 +322,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, true); EXPECT_EQ (el.bboxes_all_dirty, true); EXPECT_EQ (el.hier_dirty, true); // OK - see above + EXPECT_EQ (g.hier_generation_id (), size_t (7)); // busy mode will make events issued always g.clear (); @@ -326,6 +335,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, false); EXPECT_EQ (el.bboxes_all_dirty, false); EXPECT_EQ (el.hier_dirty, true); + EXPECT_EQ (g.hier_generation_id (), size_t (9)); el.reset (); top = &g.cell (ci); @@ -335,6 +345,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, false); EXPECT_EQ (el.bboxes_all_dirty, false); EXPECT_EQ (el.hier_dirty, true); // OK - see above + EXPECT_EQ (g.hier_generation_id (), size_t (10)); el.reset (); top->insert (db::CellInstArray (ci, db::Trans ())); @@ -343,6 +354,7 @@ TEST(2) EXPECT_EQ (el.bboxes_dirty, true); EXPECT_EQ (el.bboxes_all_dirty, true); EXPECT_EQ (el.hier_dirty, true); // OK - see above + EXPECT_EQ (g.hier_generation_id (), size_t (11)); }