diff --git a/src/db/db/dbRecursiveInstanceIterator.cc b/src/db/db/dbRecursiveInstanceIterator.cc index 31943d66c..d4a6b6aff 100644 --- a/src/db/db/dbRecursiveInstanceIterator.cc +++ b/src/db/db/dbRecursiveInstanceIterator.cc @@ -447,8 +447,8 @@ RecursiveInstanceIterator::next (RecursiveInstanceReceiver *receiver) } else { ++m_inst; new_inst (receiver); - next_instance (receiver); } + next_instance (receiver); } } @@ -463,35 +463,42 @@ RecursiveInstanceIterator::next_instance (RecursiveInstanceReceiver *receiver) c { while (true) { - if (! m_inst.at_end ()) { + while (true) { - if (int (m_inst_iterators.size ()) < m_max_depth && (m_all_targets || m_target_tree.find (m_inst->cell_index ()) != m_target_tree.end ())) { - down (receiver); - } + if (! m_inst.at_end ()) { - } else { + if (int (m_inst_iterators.size ()) < m_max_depth && (m_all_targets || m_target_tree.find (m_inst->cell_index ()) != m_target_tree.end ())) { + down (receiver); + } else { + break; + } - if (! m_inst_iterators.empty ()) { - // no more instances: up and next instance - up (receiver); } else { + + if (! m_inst_iterators.empty ()) { + // no more instances: up and next instance + up (receiver); + } break; + } } - if (! m_inst.at_end ()) { - if (! needs_visit ()) { - ++m_inst_array; - if (! m_inst_array.at_end ()) { - new_inst_member (receiver); - } else { - ++m_inst; - new_inst (receiver); - } + if (m_inst.at_end ()) { + break; + } + + if (! needs_visit ()) { + ++m_inst_array; + if (! m_inst_array.at_end ()) { + new_inst_member (receiver); } else { - break; + ++m_inst; + new_inst (receiver); } + } else { + break; } } diff --git a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc index d95615e07..07cb5fa26 100644 --- a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc +++ b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc @@ -24,12 +24,14 @@ #include "dbRecursiveInstanceIterator.h" #include "dbRegion.h" #include "dbLayoutDiff.h" +#include "dbReader.h" #include "tlString.h" #include "tlUnitTest.h" +#include "tlStream.h" #include -std::string collect(db::RecursiveInstanceIterator &s, const db::Layout &layout) +std::string collect (db::RecursiveInstanceIterator &s, const db::Layout &layout) { std::string res; while (! s.at_end ()) { @@ -47,13 +49,26 @@ std::string collect(db::RecursiveInstanceIterator &s, const db::Layout &layout) return res; } -std::string collect_with_copy(db::RecursiveInstanceIterator s, const db::Layout &layout) +std::string collect_with_copy (db::RecursiveInstanceIterator s, const db::Layout &layout) { s.reset (); return collect (s, layout); } -TEST(1) +std::string collect2 (db::RecursiveInstanceIterator &s, const db::Layout &layout) +{ + std::string res; + while (! s.at_end ()) { + if (! res.empty ()) { + res += "\n"; + } + res += std::string (layout.cell_name (s->inst_ptr.cell_index ())) + "@" + (s.trans () * s.instance ().complex_trans ()).to_string (); + ++s; + } + return res; +} + +TEST(1) { db::Manager m (true); db::Layout g (&m); @@ -660,3 +675,117 @@ TEST(5) x = collect(i1, *g); EXPECT_EQ (x, ""); } + +// issue-1353 +TEST(6) +{ + db::Layout layout; + + { + std::string fn (tl::testdata ()); + fn += "/gds/issue-1353.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (layout); + } + + std::string x; + + db::cell_index_type c1 = layout.cell_by_name ("TOP_CELL_3_C").second; + db::cell_index_type c2 = layout.cell_by_name ("TOP_CELL_3_B").second; + db::RecursiveInstanceIterator i1 (layout, layout.cell (c1)); + + x = collect2(i1, layout); + EXPECT_EQ (x, + // depth-first traversal + "CHILD_CELL_3_1_1@r0 *1 30000,0\n" + "CHILD_CELL_3_1@r0 *1 30000,0\n" + "CHILD_CELL_3@r0 *1 30000,0\n" + "CHILD_CELL_3_1_1@r0 *1 55000,0\n" + "CHILD_CELL_3_1@r0 *1 55000,0\n" + "CHILD_CELL_3@r0 *1 55000,0\n" + "CHILD_CELL_3_1_1@r0 *1 55000,20000\n" + "CHILD_CELL_3_1@r0 *1 55000,20000\n" + "CHILD_CELL_3@r0 *1 55000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 55000,40000\n" + "CHILD_CELL_3_1@r0 *1 55000,40000\n" + "CHILD_CELL_3@r0 *1 55000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 75000,0\n" + "CHILD_CELL_3_1@r0 *1 75000,0\n" + "CHILD_CELL_3@r0 *1 75000,0\n" + "CHILD_CELL_3_1_1@r0 *1 75000,20000\n" + "CHILD_CELL_3_1@r0 *1 75000,20000\n" + "CHILD_CELL_3@r0 *1 75000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 75000,40000\n" + "CHILD_CELL_3_1@r0 *1 75000,40000\n" + "CHILD_CELL_3@r0 *1 75000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 95000,0\n" + "CHILD_CELL_3_1@r0 *1 95000,0\n" + "CHILD_CELL_3@r0 *1 95000,0\n" + "CHILD_CELL_3_1_1@r0 *1 95000,20000\n" + "CHILD_CELL_3_1@r0 *1 95000,20000\n" + "CHILD_CELL_3@r0 *1 95000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 95000,40000\n" + "CHILD_CELL_3_1@r0 *1 95000,40000\n" + "CHILD_CELL_3@r0 *1 95000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 30000,20000\n" + "CHILD_CELL_3_1@r0 *1 30000,20000\n" + "CHILD_CELL_3@r0 *1 30000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 30000,40000\n" + "CHILD_CELL_3_1@r0 *1 30000,40000\n" + "CHILD_CELL_3@r0 *1 30000,40000" + ); + + std::set t; + t.insert (layout.cell_by_name ("TOP_CELL_3_1_1").second); + i1.set_targets (t); + + x = collect2(i1, layout); + EXPECT_EQ (x, + "CHILD_CELL_3_1_1@r0 *1 30000,0\n" + "CHILD_CELL_3_1_1@r0 *1 55000,0\n" + "CHILD_CELL_3_1_1@r0 *1 55000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 55000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 75000,0\n" + "CHILD_CELL_3_1_1@r0 *1 75000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 75000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 95000,0\n" + "CHILD_CELL_3_1_1@r0 *1 95000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 95000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 30000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 30000,40000" + ); + + db::RecursiveInstanceIterator i2 (layout, layout.cell (c2)); + i2.set_targets (t); + + x = collect2(i2, layout); + EXPECT_EQ (x, + "CHILD_CELL_3_1_1@r0 *1 30000,0\n" + "CHILD_CELL_3_1_1@r0 *1 55000,0\n" + "CHILD_CELL_3_1_1@r0 *1 55000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 55000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 75000,0\n" + "CHILD_CELL_3_1_1@r0 *1 75000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 75000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 95000,0\n" + "CHILD_CELL_3_1_1@r0 *1 95000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 95000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 30000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 30000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 120000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 120000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 120000,0" + ); + + std::set sc; + sc.insert (layout.cell_by_name ("CHILD_CELL_3").second); + i2.unselect_cells (sc); + + x = collect2(i2, layout); + EXPECT_EQ (x, + "CHILD_CELL_3_1_1@r0 *1 120000,20000\n" + "CHILD_CELL_3_1_1@r0 *1 120000,40000\n" + "CHILD_CELL_3_1_1@r0 *1 120000,0" + ); +} diff --git a/testdata/gds/issue-1353.gds b/testdata/gds/issue-1353.gds new file mode 100644 index 000000000..31874eeef Binary files /dev/null and b/testdata/gds/issue-1353.gds differ