mirror of https://github.com/KLayout/klayout.git
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.
This commit is contained in:
parent
902375cc4d
commit
d244d5aac6
|
|
@ -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<db::cell_index_type> CellMapping::source_cells () const
|
||||
{
|
||||
std::vector<db::cell_index_type> s;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_map)
|
||||
{
|
||||
invalidate_hier ();
|
||||
|
||||
db::HierarchyBuilder &builder = m_layouts [layout_index]->builder;
|
||||
for (std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator i = var_map.begin (); i != var_map.end (); ++i) {
|
||||
for (std::map<db::ICplxTrans, db::cell_index_type>::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::ce
|
|||
}
|
||||
|
||||
const db::CellMapping &
|
||||
DeepShapeStore::internal_cell_mapping (unsigned int from_layout_index, unsigned int into_layout_index)
|
||||
DeepShapeStore::internal_cell_mapping (unsigned int into_layout_index, unsigned int from_layout_index)
|
||||
{
|
||||
std::map<std::pair<unsigned int, unsigned int>, 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<std::pair<unsigned int, unsigned int>, 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<DeliveryMappingCacheKey, db::CellMapping>::iterator cm = m_delivery_mapping_cache.find (key);
|
||||
if (cm == m_delivery_mapping_cache.end ()) {
|
||||
std::map<DeliveryMappingCacheKey, CellMappingWithGenerationIds>::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<db::cell_index_type, db::HierarchyBuilder::CellMapKey> 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;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbHierarchyBuilder.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "gsiObject.h"
|
||||
|
||||
#include <set>
|
||||
|
|
@ -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<DeliveryMappingCacheKey, db::CellMapping> m_delivery_mapping_cache;
|
||||
std::map<std::pair<unsigned int, unsigned int>, db::CellMapping> m_internal_mapping_cache;
|
||||
std::map<DeliveryMappingCacheKey, CellMappingWithGenerationIds> m_delivery_mapping_cache;
|
||||
std::map<std::pair<unsigned int, unsigned int>, CellMappingWithGenerationIds> m_internal_mapping_cache;
|
||||
};
|
||||
|
||||
template <class VarCollector>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<bool> m_bboxes_dirty;
|
||||
bool m_all_bboxes_dirty;
|
||||
bool m_busy;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue