diff --git a/src/db/db/dbInstances.cc b/src/db/db/dbInstances.cc index 4f1a8ca54..12804e249 100644 --- a/src/db/db/dbInstances.cc +++ b/src/db/db/dbInstances.cc @@ -280,12 +280,18 @@ void instance_iterator::release_iter () { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).~stable_iter_wp_type (); } else { basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()).~stable_iter_type (); } + } else if (m_stable) { + if (m_with_props) { + basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).~stable_unsorted_iter_wp_type (); + } else { + basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()).~stable_unsorted_iter_type (); + } } else { if (m_with_props) { basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()).~iter_wp_type (); @@ -301,12 +307,18 @@ void instance_iterator::make_iter () { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_iter_wp_type (); } else { new (&basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_iter_type (); } + } else if (m_stable) { + if (m_with_props) { + new (&basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_wp_type (); + } else { + new (&basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_type (); + } } else { if (m_with_props) { new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())) iter_wp_type (); @@ -322,18 +334,24 @@ template bool instance_iterator::operator== (const instance_iterator &d) const { - if (! (m_type == d.m_type && m_stable == d.m_stable && m_with_props == d.m_with_props)) { + if (! (m_type == d.m_type && m_stable == d.m_stable && m_with_props == d.m_with_props && m_unsorted == d.m_unsorted)) { return false; } if (m_type == TNull) { return true; } else { if (m_stable) { - if (m_with_props) { + if (m_with_props && ! m_unsorted) { return (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()) == d.basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); } else { return (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()) == d.basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); } + } else if (m_stable) { + if (m_with_props) { + return (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()) == d.basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); + } else { + return (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()) == d.basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); + } } else { if (m_with_props) { return (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()) == d.basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())); @@ -355,16 +373,23 @@ instance_iterator::operator= (const instance_iterator &iter) m_type = iter.m_type; m_stable = iter.m_stable; m_with_props = iter.m_with_props; + m_unsorted = iter.m_unsorted; m_traits = iter.m_traits; if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_iter_wp_type (iter.basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); } else { new (&basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_iter_type (iter.basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); } + } else if (m_stable) { + if (m_with_props) { + new (&basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_wp_type (iter.basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); + } else { + new (&basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())) stable_unsorted_iter_type (iter.basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); + } } else { if (m_with_props) { new (&basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())) iter_wp_type (iter.basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())); @@ -387,12 +412,18 @@ db::Box instance_iterator::quad_box () const { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { return m_traits.quad_box (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); } else { return m_traits.quad_box (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); } + } else if (m_stable) { + if (m_with_props) { + return m_traits.quad_box (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); + } else { + return m_traits.quad_box (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); + } } else { if (m_with_props) { return m_traits.quad_box (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())); @@ -409,12 +440,18 @@ size_t instance_iterator::quad_id () const { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { return m_traits.quad_id (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); } else { return m_traits.quad_id (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); } + } else if (m_stable) { + if (m_with_props) { + return m_traits.quad_id (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); + } else { + return m_traits.quad_id (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); + } } else { if (m_with_props) { return m_traits.quad_id (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())); @@ -431,12 +468,18 @@ void instance_iterator::skip_quad () { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { m_traits.skip_quad (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); } else { m_traits.skip_quad (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); } + } else if (m_stable) { + if (m_with_props) { + m_traits.skip_quad (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); + } else { + m_traits.skip_quad (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); + } } else { if (m_with_props) { m_traits.skip_quad (basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())); @@ -454,12 +497,18 @@ instance_iterator & instance_iterator::operator++() { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { ++basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()); } else { ++basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ()); } + } else if (m_stable) { + if (m_with_props) { + ++basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()); + } else { + ++basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()); + } } else { if (m_with_props) { ++basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()); @@ -478,7 +527,7 @@ void instance_iterator::make_next () { while (true) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { if (! basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).at_end ()) { return; @@ -488,6 +537,16 @@ instance_iterator::make_next () return; } } + } else if (m_stable) { + if (m_with_props) { + if (! basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ()).at_end ()) { + return; + } + } else { + if (! basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ()).at_end ()) { + return; + } + } } else { if (m_with_props) { if (! basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ()).at_end ()) { @@ -514,12 +573,18 @@ void instance_iterator::update_ref () { if (m_type == TInstance) { - if (m_stable) { + if (m_stable && ! m_unsorted) { if (m_with_props) { m_ref = m_traits.instance_from_stable_iter (basic_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); } else { m_ref = m_traits.instance_from_stable_iter (basic_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); } + } else if (m_stable) { + if (m_with_props) { + m_ref = m_traits.instance_from_stable_iter (basic_unsorted_iter (cell_inst_wp_array_type::tag (), InstancesEditableTag ())); + } else { + m_ref = m_traits.instance_from_stable_iter (basic_unsorted_iter (cell_inst_array_type::tag (), InstancesEditableTag ())); + } } else { if (m_with_props) { m_ref = value_type (m_traits.instances (), *basic_iter (cell_inst_wp_array_type::tag (), InstancesNonEditableTag ())); @@ -551,7 +616,7 @@ void NormalInstanceIteratorTraits::init (instance_iterator *iter) const { tl_assert (mp_insts != 0); - if (iter->m_stable) { + if (iter->m_stable && ! iter->m_unsorted) { if (iter->m_with_props) { cell_inst_wp_array_type::tag tag = cell_inst_wp_array_type::tag (); iter->basic_iter (tag, InstancesEditableTag ()) = mp_insts->inst_tree (tag, InstancesEditableTag ()).begin_flat (); @@ -559,6 +624,14 @@ NormalInstanceIteratorTraits::init (instance_iteratorbasic_iter (tag, InstancesEditableTag ()) = mp_insts->inst_tree (tag, InstancesEditableTag ()).begin_flat (); } + } else if (iter->m_stable) { + if (iter->m_with_props) { + cell_inst_wp_array_type::tag tag = cell_inst_wp_array_type::tag (); + iter->basic_unsorted_iter (tag, InstancesEditableTag ()) = stable_unsorted_iter_wp_type (mp_insts->inst_tree (tag, InstancesEditableTag ()).begin (), mp_insts->inst_tree (tag, InstancesEditableTag ()).end ()); + } else { + cell_inst_array_type::tag tag = cell_inst_array_type::tag (); + iter->basic_unsorted_iter (tag, InstancesEditableTag ()) = stable_unsorted_iter_type (mp_insts->inst_tree (tag, InstancesEditableTag ()).begin (), mp_insts->inst_tree (tag, InstancesEditableTag ()).end ()); + } } else { if (iter->m_with_props) { cell_inst_wp_array_type::tag tag = cell_inst_wp_array_type::tag (); diff --git a/src/db/db/dbInstances.h b/src/db/db/dbInstances.h index 975904e28..a9f11a17d 100644 --- a/src/db/db/dbInstances.h +++ b/src/db/db/dbInstances.h @@ -527,7 +527,9 @@ public: typedef typename IterTraits::iter_wp_type iter_wp_type; typedef typename IterTraits::stable_iter_type stable_iter_type; typedef typename IterTraits::stable_iter_wp_type stable_iter_wp_type; - typedef const value_type *pointer; + typedef typename IterTraits::stable_unsorted_iter_type stable_unsorted_iter_type; + typedef typename IterTraits::stable_unsorted_iter_wp_type stable_unsorted_iter_wp_type; + typedef const value_type *pointer; typedef value_type reference; // operator* returns a value typedef std::forward_iterator_tag iterator_category; typedef void difference_type; @@ -541,7 +543,7 @@ public: * @brief Default ctor */ instance_iterator () - : m_with_props (false), m_stable (false), m_type (TNull), m_traits () + : m_type (TNull), m_with_props (false), m_stable (false), m_unsorted (false), m_traits () { } /** @@ -556,7 +558,7 @@ public: * @brief Constructor */ instance_iterator (const IterTraits &traits) - : m_with_props (false), m_stable (traits.instances ()->is_editable ()), m_type (TInstance), m_traits (traits) + : m_type (TInstance), m_with_props (false), m_stable (traits.instances ()->is_editable ()), m_unsorted (traits.instances ()->instance_tree_needs_sort ()), m_traits (traits) { make_iter (); make_next (); @@ -567,7 +569,7 @@ public: * @brief Copy constructor */ instance_iterator (const instance_iterator &iter) - : m_with_props (false), m_stable (false), m_type (TNull), m_traits () + : m_type (TNull), m_with_props (false), m_stable (false), m_unsorted (false), m_traits () { operator= (iter); } @@ -661,7 +663,7 @@ public: */ stable_iter_type &basic_iter (cell_inst_array_type::tag, InstancesEditableTag) { - tl_assert (m_type == TInstance && m_stable == true && m_with_props == false); + tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == false); return *((stable_iter_type *) m_generic.stable_iter); } @@ -670,10 +672,28 @@ public: */ const stable_iter_type &basic_iter (cell_inst_array_type::tag, InstancesEditableTag) const { - tl_assert (m_type == TInstance && m_stable == true && m_with_props == false); + tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == false); return *((stable_iter_type *) m_generic.stable_iter); } + /** + * @brief Gets the basic iterator in the editable case without properties and in the unsorted case + */ + stable_unsorted_iter_type &basic_unsorted_iter (cell_inst_array_type::tag, InstancesEditableTag) + { + tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == true); + return *((stable_unsorted_iter_type *) m_generic.stable_unsorted_iter); + } + + /** + * @brief Gets the basic iterator in the editable case without properties and in the unsorted case (const version) + */ + const stable_unsorted_iter_type &basic_unsorted_iter (cell_inst_array_type::tag, InstancesEditableTag) const + { + tl_assert (m_type == TInstance && m_stable == true && m_with_props == false && m_unsorted == true); + return *((stable_unsorted_iter_type *) m_generic.stable_unsorted_iter); + } + /** * @brief Gets the basic iterator in the non-editable case with properties */ @@ -697,7 +717,7 @@ public: */ stable_iter_wp_type &basic_iter (cell_inst_wp_array_type::tag, InstancesEditableTag) { - tl_assert (m_type == TInstance && m_stable == true && m_with_props == true); + tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == false); return *((stable_iter_wp_type *) m_generic.pstable_iter); } @@ -706,10 +726,28 @@ public: */ const stable_iter_wp_type &basic_iter (cell_inst_wp_array_type::tag, InstancesEditableTag) const { - tl_assert (m_type == TInstance && m_stable == true && m_with_props == true); + tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == false); return *((stable_iter_wp_type *) m_generic.pstable_iter); } + /** + * @brief Gets the basic iterator in the editable case with properties and in the unsorted case + */ + stable_unsorted_iter_wp_type &basic_unsorted_iter (cell_inst_wp_array_type::tag, InstancesEditableTag) + { + tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == true); + return *((stable_unsorted_iter_wp_type *) m_generic.pstable_unsorted_iter); + } + + /** + * @brief Gets the basic iterator in the editable case with properties and in the unsorted case (const version) + */ + const stable_unsorted_iter_wp_type &basic_unsorted_iter (cell_inst_wp_array_type::tag, InstancesEditableTag) const + { + tl_assert (m_type == TInstance && m_stable == true && m_with_props == true && m_unsorted == true); + return *((stable_unsorted_iter_wp_type *) m_generic.pstable_unsorted_iter); + } + private: friend struct NormalInstanceIteratorTraits; friend struct OverlappingInstanceIteratorTraits; @@ -720,11 +758,14 @@ private: char piter[sizeof (iter_wp_type)]; char stable_iter[sizeof (stable_iter_type)]; char pstable_iter[sizeof (stable_iter_wp_type)]; + char stable_unsorted_iter[sizeof (stable_unsorted_iter_type)]; + char pstable_unsorted_iter[sizeof (stable_unsorted_iter_wp_type)]; } m_generic; - bool m_with_props : 8; - bool m_stable : 8; object_type m_type : 16; + bool m_with_props : 1; + bool m_stable : 1; + bool m_unsorted : 1; value_type m_ref; IterTraits m_traits; @@ -759,6 +800,8 @@ struct DB_PUBLIC NormalInstanceIteratorTraits typedef tl::iterator_pair iter_wp_type; typedef stable_cell_inst_tree_type::flat_iterator stable_iter_type; typedef stable_cell_inst_wp_tree_type::flat_iterator stable_iter_wp_type; + typedef tl::iterator_pair stable_unsorted_iter_type; + typedef tl::iterator_pair stable_unsorted_iter_wp_type; NormalInstanceIteratorTraits (); NormalInstanceIteratorTraits (const instances_type *insts); @@ -804,6 +847,8 @@ struct DB_PUBLIC TouchingInstanceIteratorTraits typedef cell_inst_wp_tree_type::touching_iterator iter_wp_type; typedef stable_cell_inst_tree_type::touching_iterator stable_iter_type; typedef stable_cell_inst_wp_tree_type::touching_iterator stable_iter_wp_type; + typedef stable_iter_type stable_unsorted_iter_type; + typedef stable_iter_wp_type stable_unsorted_iter_wp_type; TouchingInstanceIteratorTraits (); TouchingInstanceIteratorTraits (const instances_type *insts, const box_type &box, const layout_type *layout); @@ -855,6 +900,8 @@ struct DB_PUBLIC OverlappingInstanceIteratorTraits typedef cell_inst_wp_tree_type::overlapping_iterator iter_wp_type; typedef stable_cell_inst_tree_type::overlapping_iterator stable_iter_type; typedef stable_cell_inst_wp_tree_type::overlapping_iterator stable_iter_wp_type; + typedef stable_iter_type stable_unsorted_iter_type; + typedef stable_iter_wp_type stable_unsorted_iter_wp_type; OverlappingInstanceIteratorTraits (); OverlappingInstanceIteratorTraits (const instances_type *insts, const box_type &box, const layout_type *layout); @@ -1741,6 +1788,7 @@ private: friend struct NormalInstanceIteratorTraits; friend struct TouchingInstanceIteratorTraits; friend struct OverlappingInstanceIteratorTraits; + template friend class instance_iterator; template friend class InstOp; union { @@ -1773,7 +1821,7 @@ private: } /** - * @brief Sets a flag indicating that the instance tree needs sorting + * @brief Gets a flag indicating that the instance tree needs sorting */ bool instance_tree_needs_sort () const { diff --git a/src/db/unit_tests/dbLayoutTests.cc b/src/db/unit_tests/dbLayoutTests.cc index 6bd145478..02d26a22d 100644 --- a/src/db/unit_tests/dbLayoutTests.cc +++ b/src/db/unit_tests/dbLayoutTests.cc @@ -28,6 +28,7 @@ #include "dbTextWriter.h" #include "dbCellMapping.h" #include "dbInstElement.h" +#include "dbWriter.h" #include "tlString.h" #include "tlUnitTest.h" @@ -872,6 +873,68 @@ TEST(11_FindPath) EXPECT_EQ (d, "cell_index=1 r90 *1 0,0;cell_index=2 r0 *1 100,200"); } +// Shapes can be flat-iterated even in locked layout +TEST(12_ShapesInLockedLayout) +{ + db::Layout l; + db::Cell &top = l.cell (l.add_cell ("TOP")); + unsigned int l1 = l.insert_layer (db::LayerProperties (1, 0)); + + { + db::LayoutLocker locker (&l); + EXPECT_EQ (l.under_construction (), true); + + top.shapes (l1).insert (db::Box (1, 2, 3, 4)); + top.shapes (l1).insert (db::Box (10, 20, 30, 40)); + top.shapes (l1).insert (db::Box (100, 200, 300, 400)); + + double a = 0; + for (auto s = top.shapes (l1).begin (db::ShapeIterator::All); ! s.at_end (); ++s) { + a += s->area (); + } + EXPECT_EQ (a, 40404.0); + } + + EXPECT_EQ (l.under_construction (), false); + + double a = 0; + for (auto s = top.shapes (l1).begin (db::ShapeIterator::All); ! s.at_end (); ++s) { + a += s->area (); + } + EXPECT_EQ (a, 40404.0); +} + +// Instances can be flat-iterated even in locked layout +TEST(13_InstancesInLockedLayout) +{ + db::Layout l; + db::Cell &top = l.cell (l.add_cell ("TOP")); + db::Cell &c = l.cell (l.add_cell ("C")); + + { + db::LayoutLocker locker (&l); + EXPECT_EQ (l.under_construction (), true); + + top.insert (db::CellInstArray (c.cell_index (), db::Trans (db::Vector (10, 20)))); + top.insert (db::CellInstArray (c.cell_index (), db::Trans (db::Vector (100, 200)))); + top.insert (db::CellInstArray (c.cell_index (), db::Trans (db::Vector (1, 2)))); + + db::Vector a; + for (auto i = top.begin (); ! i.at_end (); ++i) { + a += i->cell_inst ().front ().disp (); + } + EXPECT_EQ (a.to_string (), "111,222"); + } + + EXPECT_EQ (l.under_construction (), false); + + db::Vector a; + for (auto i = top.begin (); ! i.at_end (); ++i) { + a += i->cell_inst ().front ().disp (); + } + EXPECT_EQ (a.to_string (), "111,222"); +} + // issue #1860 TEST(100_UndoOfDeleteLayer) {