diff --git a/src/db/db/dbRecursiveInstanceIterator.cc b/src/db/db/dbRecursiveInstanceIterator.cc index 2b9efb3d0..e06a5f09b 100644 --- a/src/db/db/dbRecursiveInstanceIterator.cc +++ b/src/db/db/dbRecursiveInstanceIterator.cc @@ -61,6 +61,7 @@ RecursiveInstanceIterator &RecursiveInstanceIterator::operator= (const Recursive m_box_convert = d.m_box_convert; + m_locker = d.m_locker; m_inst = d.m_inst; m_inst_array = d.m_inst_array; m_empty_cells_cache = d.m_empty_cells_cache; @@ -175,7 +176,7 @@ RecursiveInstanceIterator::set_region (const box_type ®ion) { if (m_region != region || mp_complex_region.get () != 0) { init_region (region); - m_needs_reinit = true; + reset (); } } @@ -183,7 +184,7 @@ void RecursiveInstanceIterator::set_region (const region_type ®ion) { init_region (region); - m_needs_reinit = true; + reset (); } void @@ -196,7 +197,7 @@ RecursiveInstanceIterator::confine_region (const box_type ®ion) } else { init_region (m_region & region); } - m_needs_reinit = true; + reset (); } void @@ -209,7 +210,7 @@ RecursiveInstanceIterator::confine_region (const region_type ®ion) } else { init_region (region & region_type (m_region)); } - m_needs_reinit = true; + reset (); } void @@ -218,7 +219,7 @@ RecursiveInstanceIterator::enable_all_targets () if (! m_all_targets) { m_all_targets = true; m_targets.clear (); - m_needs_reinit = true; + reset (); } } @@ -228,7 +229,7 @@ RecursiveInstanceIterator::set_targets (const std::set &tgt if (m_all_targets || m_targets != tgt) { m_targets = tgt; m_all_targets = false; - m_needs_reinit = true; + reset (); } } @@ -264,6 +265,8 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const m_needs_reinit = false; // re-initialize + m_locker = db::LayoutLocker (); + mp_cell = mp_top_cell; m_trans_stack.clear (); m_inst_iterators.clear (); @@ -310,6 +313,17 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const next_instance (receiver); } + + if (mp_layout && ! at_end ()) { + m_locker = db::LayoutLocker (const_cast (mp_layout.get ()), true); + } +} + +void +RecursiveInstanceIterator::reset () +{ + m_needs_reinit = true; + m_locker = db::LayoutLocker (); } void @@ -320,7 +334,7 @@ RecursiveInstanceIterator::reset_selection () m_start.clear (); m_stop.clear (); - m_needs_reinit = true; + reset (); } } @@ -335,7 +349,7 @@ RecursiveInstanceIterator::unselect_cells (const std::set & m_start.erase (*c); } - m_needs_reinit = true; + reset (); } } @@ -350,7 +364,7 @@ RecursiveInstanceIterator::unselect_all_cells () m_stop.insert (c->cell_index ()); } - m_needs_reinit = true; + reset (); } } @@ -365,7 +379,7 @@ RecursiveInstanceIterator::select_cells (const std::set &ce m_stop.erase (*c); } - m_needs_reinit = true; + reset (); } } @@ -380,7 +394,7 @@ RecursiveInstanceIterator::select_all_cells () m_start.insert (c->cell_index ()); } - m_needs_reinit = true; + reset (); } } @@ -441,6 +455,7 @@ void RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver) { if (! at_end ()) { + ++m_inst_array; if (! m_inst_array.at_end ()) { new_inst_member (receiver); @@ -449,6 +464,12 @@ RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver) new_inst (receiver); } next_instance (receiver); + + if (at_end ()) { + // Take this opportunity the release the layout lock. + // This way, the shape iterator can be held further, without blocking the layout. + m_locker = db::LayoutLocker (); + } } } diff --git a/src/db/db/dbRecursiveInstanceIterator.h b/src/db/db/dbRecursiveInstanceIterator.h index dd06c5cf5..5b746fbf3 100644 --- a/src/db/db/dbRecursiveInstanceIterator.h +++ b/src/db/db/dbRecursiveInstanceIterator.h @@ -141,7 +141,7 @@ public: { if (m_max_depth != depth) { m_max_depth = depth; - m_needs_reinit = true; + reset (); } } @@ -164,7 +164,7 @@ public: { if (m_min_depth != depth) { m_min_depth = depth; - m_needs_reinit = true; + reset (); } } @@ -262,17 +262,14 @@ public: { if (m_overlapping != f) { m_overlapping = f; - m_needs_reinit = true; + reset (); } } /** * @brief Reset the iterator */ - void reset () - { - m_needs_reinit = true; - } + void reset (); /** * @brief Gets the selected target cells @@ -552,6 +549,7 @@ private: std::unique_ptr mp_complex_region; db::box_convert m_box_convert; + mutable db::LayoutLocker m_locker; mutable inst_iterator m_inst; mutable inst_array_iterator m_inst_array; mutable instance_element_type m_combined_instance; diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index 27d86e2aa..d9994162f 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -511,7 +511,14 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const } } -void +void +RecursiveShapeIterator::reset () +{ + m_needs_reinit = true; + m_locker = db::LayoutLocker (); +} + +void RecursiveShapeIterator::reset_selection () { if (mp_layout) { @@ -554,13 +561,6 @@ RecursiveShapeIterator::unselect_all_cells () } } -void -RecursiveShapeIterator::reset () -{ - m_needs_reinit = true; - m_locker = db::LayoutLocker (); -} - void RecursiveShapeIterator::select_cells (const std::set &cells) { diff --git a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc index eb06a6967..92ff90e4d 100644 --- a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc +++ b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc @@ -790,3 +790,69 @@ TEST(6) ); } +// layout locking +TEST(7_LayoutLocking) +{ + db::Layout layout; + + layout.insert_layer (0); + + db::Cell &c0 (layout.cell (layout.add_cell ())); + db::Cell &c1 (layout.cell (layout.add_cell ())); + + db::Box b (0, 100, 1000, 1200); + c1.shapes (0).insert (b); + + db::Trans tt; + c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt)); + c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (2000, -2000)))); + + EXPECT_EQ (layout.under_construction (), false); + + db::RecursiveInstanceIterator iter (layout, c0); + + EXPECT_EQ (layout.under_construction (), false); + + EXPECT_EQ (iter.at_end (), false); + EXPECT_EQ (layout.under_construction (), true); + + EXPECT_EQ (iter.instance ().to_string (), "cell_index=1 r0 *1 0,0"); + EXPECT_EQ (layout.under_construction (), true); + ++iter; + + EXPECT_EQ (iter.at_end (), false); + + EXPECT_EQ (iter.instance ().to_string (), "cell_index=1 r0 *1 2000,-2000"); + EXPECT_EQ (layout.under_construction (), true); + ++iter; + + EXPECT_EQ (layout.under_construction (), false); + EXPECT_EQ (iter.at_end (), true); + + // reset will restart + iter.reset (); + + EXPECT_EQ (layout.under_construction (), false); + + EXPECT_EQ (iter.at_end (), false); + EXPECT_EQ (layout.under_construction (), true); + + // a copy will hold the lock + iter.reset (); + + EXPECT_EQ (layout.under_construction (), false); + EXPECT_EQ (iter.at_end (), false); + + EXPECT_EQ (layout.under_construction (), true); + db::RecursiveInstanceIterator iter_copy = iter; + + while (! iter.at_end ()) { + ++iter; + } + + EXPECT_EQ (layout.under_construction (), true); + iter_copy = db::RecursiveInstanceIterator (); + + EXPECT_EQ (layout.under_construction (), false); +} +