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:
Matthias Koefferlein 2021-11-01 13:48:47 +01:00
parent 902375cc4d
commit d244d5aac6
8 changed files with 94 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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