WIP: Some hardening against internal state changes in RecursiveShapeIterator, tests fixed

This commit is contained in:
Matthias Koefferlein 2021-05-25 21:36:54 +02:00
parent 1c8442f485
commit 0452e91e8c
3 changed files with 33 additions and 22 deletions

View File

@ -402,10 +402,11 @@ static size_t s_instance_count = 0;
static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIterator &si) static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIterator &si)
{ {
unsigned int layer_index = layout.insert_layer (); unsigned int layer_index = layout.insert_layer ();
unsigned int iter_layer = si.multiple_layers () ? si.layers ().front () : si.layer ();
if (si.layout () && si.layer () < si.layout ()->layers ()) { if (si.layout () && iter_layer < si.layout ()->layers ()) {
// try to preserve the layer properties // try to preserve the layer properties
layout.set_properties (layer_index, si.layout ()->get_properties (si.layer ())); layout.set_properties (layer_index, si.layout ()->get_properties (iter_layer));
} }
return layer_index; return layer_index;

View File

@ -190,11 +190,15 @@ OriginalLayerRegion::min_coherence_changed ()
size_t size_t
OriginalLayerRegion::count () const OriginalLayerRegion::count () const
{ {
if (m_iter.has_complex_region () || m_iter.region () != db::Box::world () || ! m_iter.enables ().empty () || ! m_iter.disables ().empty ()) { // NOTE: we should to make sure the iterator isn't validated as this would spoil the usability or OriginalLayerRegion upon
// layout changes
db::RecursiveShapeIterator iter = m_iter;
if (iter.has_complex_region () || iter.region () != db::Box::world () || ! iter.enables ().empty () || ! iter.disables ().empty ()) {
// complex case with a search region - use the iterator to determine the count (expensive) // complex case with a search region - use the iterator to determine the count (expensive)
size_t n = 0; size_t n = 0;
for (db::RecursiveShapeIterator i = m_iter; ! i.at_end (); ++i) { for (db::RecursiveShapeIterator i = iter; ! i.at_end (); ++i) {
++n; ++n;
} }
@ -206,11 +210,11 @@ OriginalLayerRegion::count () const
size_t n = 0; size_t n = 0;
const db::Layout &layout = *m_iter.layout (); const db::Layout &layout = *iter.layout ();
std::set<db::cell_index_type> cells; std::set<db::cell_index_type> cells;
m_iter.top_cell ()->collect_called_cells (cells); iter.top_cell ()->collect_called_cells (cells);
cells.insert (m_iter.top_cell ()->cell_index ()); cells.insert (iter.top_cell ()->cell_index ());
db::CellCounter cc (&layout); db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) { for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
@ -218,12 +222,12 @@ OriginalLayerRegion::count () const
continue; continue;
} }
size_t nn = 0; size_t nn = 0;
if (m_iter.multiple_layers ()) { if (iter.multiple_layers ()) {
for (std::vector<unsigned int>::const_iterator l = m_iter.layers ().begin (); l != m_iter.layers ().end (); ++l) { for (std::vector<unsigned int>::const_iterator l = iter.layers ().begin (); l != iter.layers ().end (); ++l) {
nn += layout.cell (*c).shapes (*l).size (m_iter.shape_flags ()); nn += layout.cell (*c).shapes (*l).size (iter.shape_flags ());
} }
} else { } else {
nn += layout.cell (*c).shapes (m_iter.layer ()).size (m_iter.shape_flags ()); nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags ());
} }
n += cc.weight (*c) * nn; n += cc.weight (*c) * nn;
} }
@ -236,7 +240,11 @@ OriginalLayerRegion::count () const
size_t size_t
OriginalLayerRegion::hier_count () const OriginalLayerRegion::hier_count () const
{ {
if (m_iter.has_complex_region () || m_iter.region () != db::Box::world ()) { // NOTE: we should to make sure the iterator isn't validated as this would spoil the usability or OriginalLayerRegion upon
// layout changes
db::RecursiveShapeIterator iter = m_iter;
if (iter.has_complex_region () || iter.region () != db::Box::world ()) {
// TODO: how to establish a "hierarchical" interpretation in this case? // TODO: how to establish a "hierarchical" interpretation in this case?
return count (); return count ();
@ -245,22 +253,22 @@ OriginalLayerRegion::hier_count () const
size_t n = 0; size_t n = 0;
const db::Layout &layout = *m_iter.layout (); const db::Layout &layout = *iter.layout ();
std::set<db::cell_index_type> cells; std::set<db::cell_index_type> cells;
m_iter.top_cell ()->collect_called_cells (cells); iter.top_cell ()->collect_called_cells (cells);
cells.insert (m_iter.top_cell ()->cell_index ()); cells.insert (iter.top_cell ()->cell_index ());
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) { for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
if (cells.find (*c) == cells.end ()) { if (cells.find (*c) == cells.end ()) {
continue; continue;
} }
if (m_iter.multiple_layers ()) { if (iter.multiple_layers ()) {
for (std::vector<unsigned int>::const_iterator l = m_iter.layers ().begin (); l != m_iter.layers ().end (); ++l) { for (std::vector<unsigned int>::const_iterator l = iter.layers ().begin (); l != iter.layers ().end (); ++l) {
n += layout.cell (*c).shapes (*l).size (m_iter.shape_flags ()); n += layout.cell (*c).shapes (*l).size (iter.shape_flags ());
} }
} else { } else {
n += layout.cell (*c).shapes (m_iter.layer ()).size (m_iter.shape_flags ()); n += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags ());
} }
} }

View File

@ -550,11 +550,13 @@ public:
} }
/** /**
* @brief Get the layer of the current shape * @brief Gets the layer of the current shape
*/ */
unsigned int layer () const unsigned int layer () const
{ {
validate (0); if (m_has_layers) {
validate (0);
}
return m_layer; return m_layer;
} }
@ -562,7 +564,7 @@ public:
* @brief Gets the layers from which the shapes are taken from * @brief Gets the layers from which the shapes are taken from
* *
* The returned layers are useful only if \multiple_layers is * The returned layers are useful only if \multiple_layers is
* true. * true. Otherwise use \layer to get the iterated layer.
*/ */
const std::vector<unsigned int> &layers () const const std::vector<unsigned int> &layers () const
{ {