diff --git a/src/db/db/dbRecursiveInstanceIterator.cc b/src/db/db/dbRecursiveInstanceIterator.cc index 257d49550..60577cf67 100644 --- a/src/db/db/dbRecursiveInstanceIterator.cc +++ b/src/db/db/dbRecursiveInstanceIterator.cc @@ -83,7 +83,6 @@ RecursiveInstanceIterator &RecursiveInstanceIterator::operator= (const Recursive RecursiveInstanceIterator::RecursiveInstanceIterator () { // anything. Not necessary reasonable. - mp_layout = 0; mp_top_cell = 0; mp_cell = 0; m_overlapping = false; @@ -97,7 +96,7 @@ RecursiveInstanceIterator::RecursiveInstanceIterator () RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const box_type ®ion, bool overlapping) : m_box_convert (layout) { - mp_layout = &layout; + mp_layout = const_cast (&layout); mp_top_cell = &cell; m_overlapping = overlapping; init (); @@ -107,7 +106,7 @@ RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const region_type ®ion, bool overlapping) : m_box_convert (layout) { - mp_layout = &layout; + mp_layout = const_cast (&layout); mp_top_cell = &cell; m_overlapping = overlapping; init (); @@ -117,7 +116,7 @@ RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell) : m_box_convert (layout) { - mp_layout = &layout; + mp_layout = const_cast (&layout); mp_top_cell = &cell; m_overlapping = false; init (); @@ -272,6 +271,7 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const m_inst_array_iterators.clear (); m_cells.clear (); m_trans = cplx_trans_type (); + m_target_tree.clear (); m_local_region_stack.clear (); m_local_region_stack.push_back (m_region); @@ -300,10 +300,9 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const } - if (mp_top_cell) { + if (mp_top_cell && mp_layout) { if (! m_all_targets) { - m_target_tree.clear (); mp_top_cell->collect_called_cells (m_target_tree); } @@ -501,6 +500,8 @@ RecursiveInstanceIterator::next_instance (RecursiveInstanceReceiver *receiver) c void RecursiveInstanceIterator::down (RecursiveInstanceReceiver *receiver) const { + tl_assert (mp_layout); + m_trans_stack.push_back (m_trans); m_cells.push_back (mp_cell); diff --git a/src/db/db/dbRecursiveInstanceIterator.h b/src/db/db/dbRecursiveInstanceIterator.h index 7f1f671b3..29fafcdda 100644 --- a/src/db/db/dbRecursiveInstanceIterator.h +++ b/src/db/db/dbRecursiveInstanceIterator.h @@ -29,6 +29,7 @@ #include "dbLayout.h" #include "dbInstElement.h" #include "tlAssert.h" +#include "tlObject.h" #include #include @@ -180,7 +181,7 @@ public: */ const layout_type *layout () const { - return mp_layout; + return mp_layout.get (); } /** @@ -544,7 +545,7 @@ private: std::set m_targets; bool m_all_targets; - const layout_type *mp_layout; + tl::weak_ptr mp_layout; const cell_type *mp_top_cell; box_type m_region; diff --git a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc index e8ba49cea..6656613c7 100644 --- a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc +++ b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc @@ -619,3 +619,44 @@ TEST(4) EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); } +TEST(5) +{ + std::unique_ptr g (new db::Layout ()); + g->insert_layer (0); + g->insert_layer (1); + g->insert_layer (2); + + db::Cell &c0 (g->cell (g->add_cell ())); + db::Cell &c1 (g->cell (g->add_cell ())); + db::Cell &c2 (g->cell (g->add_cell ())); + db::Cell &c3 (g->cell (g->add_cell ())); + + db::Box b (0, 100, 1000, 1200); + c0.shapes (0).insert (b); + c1.shapes (0).insert (b); + c2.shapes (0).insert (b); + c3.shapes (0).insert (b); + + c0.shapes (2).insert (b); + c0.shapes (2).insert (b.moved (db::Vector (50, 50))); + + db::Trans tt; + c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt)); + c0.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), db::Trans (db::Vector (100, -100)))); + c0.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (1))); + c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (db::Vector (1100, 0)))); + + std::string x; + + db::RecursiveInstanceIterator i1 (*g, c0, db::Box (0, 0, 100, 100)); + x = collect(i1, *g); + EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100"); + + g.reset (new db::Layout ()); + + // now the layout is gone and the iterator stays silent (weak pointer to layout) + // NOTE: this only works on reset or re-initialization. Not during iteration. + i1.reset (); + x = collect(i1, *g); + EXPECT_EQ (x, ""); +}