diff --git a/src/db/db/dbRecursiveInstanceIterator.cc b/src/db/db/dbRecursiveInstanceIterator.cc index a52274c5c..4af46223b 100644 --- a/src/db/db/dbRecursiveInstanceIterator.cc +++ b/src/db/db/dbRecursiveInstanceIterator.cc @@ -218,7 +218,7 @@ RecursiveInstanceIterator::confine_region (const region_type ®ion) } void -RecursiveInstanceIterator::all_targets () +RecursiveInstanceIterator::enable_all_targets () { if (! m_all_targets) { m_all_targets = true; @@ -228,7 +228,7 @@ RecursiveInstanceIterator::all_targets () } void -RecursiveInstanceIterator::targets (const std::set &tgt) +RecursiveInstanceIterator::set_targets (const std::set &tgt) { if (m_all_targets || m_targets != tgt) { m_targets = tgt; diff --git a/src/db/db/dbRecursiveInstanceIterator.h b/src/db/db/dbRecursiveInstanceIterator.h index fbf1afdfe..5ac6f6168 100644 --- a/src/db/db/dbRecursiveInstanceIterator.h +++ b/src/db/db/dbRecursiveInstanceIterator.h @@ -49,11 +49,7 @@ class RecursiveInstanceReceiver; * Some options can be specified, i.e. the level to which to look into or which cells * to select. * - * The general iteration scheme is iterating is top-down and breadth-first. - * - * While the iterator delivers instances, it will first deliver the instances of cells - * and then the instances of cells inside cells whose instances have been delivered already. - * No differentiation is made for leaf or non-leaf cells. + * The general iteration scheme is iterating is depth-first and child instances before parent instances. */ class DB_PUBLIC RecursiveInstanceIterator { @@ -134,8 +130,9 @@ public: /** * @brief Specify the maximum hierarchy depth to look into * - * A depth of 0 instructs the iterator to deliver only shapes from the initial cell. - * The depth must be specified before the shapes are being retrieved. + * A depth of 0 instructs the iterator to deliver only instances from the initial cell. + * A higher depth instructs the iterator to look deeper. + * The depth must be specified before the instances are being retrieved. */ void max_depth (int depth) { @@ -156,9 +153,9 @@ public: /** * @brief Specify the minimum hierarchy depth to look into * - * A depth of 0 instructs the iterator to deliver shapes from the top level. - * 1 instructs to deliver shapes from the first child level. - * The minimum depth must be specified before the shapes are being retrieved. + * A depth of 0 instructs the iterator to deliver instance from the top level and below. + * 1 instructs to deliver instance from the first child level. + * The minimum depth must be specified before the instances are being retrieved. */ void min_depth (int depth) { @@ -248,7 +245,7 @@ public: void confine_region (const region_type ®ion); /** - * @brief Gets a flag indicating whether overlapping shapes are selected when a region is used + * @brief Gets a flag indicating whether overlapping instances are selected when a region is used */ bool overlapping () const { @@ -256,7 +253,7 @@ public: } /** - * @brief Sets a flag indicating whether overlapping shapes are selected when a region is used + * @brief Sets a flag indicating whether overlapping instances are selected when a region is used */ void set_overlapping (bool f) { @@ -277,7 +274,13 @@ public: /** * @brief Gets the selected target cells * - * Only cells from the targets section are reported if "select_all_targets" is false. + * Only instances of cells in the targets set are reported. + * By default the iterator is configured to deliver all instances. + * By using "set_targets" with a set of cell indexes, the reporting + * can be confined to certain cells only. To enable all-cell reporting + * use "enable_all_targets". + * + * "all_targets_enabled" can be used to check which mode is used. */ const std::set &targets () const { @@ -286,27 +289,38 @@ public: /** * @brief Gets a flags indicating whether all targets are selected + * See \targets for more details. */ - bool has_all_targets () const + bool all_targets_enabled () const { return m_all_targets; } /** * @brief Selects all target cells + * See \targets for more details. */ - void all_targets (); + void enable_all_targets (); /** * @brief Selects the given targets * * This will reset the "all_targets" flag to false. + * See \targets for more details. */ - void targets (const std::set &targets); + void set_targets (const std::set &set_targets); /** * @brief Select cells * + * Cell selection allows confining the hierarchy traversal to subtrees of the + * hierarchy tree. This happens by "selecting" and "unselecting" cells in the traversal path. + * "selected" cells will make iterator traverse the tree below this cell while + * "unselected" cells make the iterator ignore this cell. + * Cells which are neither selected nor unselected will be traversed depending + * on their parent's state. They are traversed if their parents are and are not traversed + * if their parents are not. + * * If no specific cells have been selected before, this method will confine the selection * to the given cells (plus their sub-hierarchy). * If cells have been selected before, this will add the given cells to the selection. @@ -318,6 +332,8 @@ public: * * Makes all cells selected. After doing so, all unselect_cells calls * will unselect only that specific cell without children. + * + * See \select_cells for more details. */ void select_all_cells (); @@ -325,6 +341,8 @@ public: * @brief Unselect cells * * This method will remove the given cells (plus their sub-hierarchy) from the selection. + * + * See \select_cells for more details. */ void unselect_cells (const std::set &cells); @@ -333,6 +351,8 @@ public: * * Makes all cells unselected. After doing so, select_cells calls * will select only that specific cell without children. + * + * See \select_cells for more details. */ void unselect_all_cells (); @@ -342,6 +362,8 @@ public: * This will reset all selections and unselections. * After calling this methods, all select_cells will again select the cells * including their children. + * + * See \select_cells for more details. */ void reset_selection (); diff --git a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc index f49a382d5..35eb4496d 100644 --- a/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc +++ b/src/db/unit_tests/dbRecursiveInstanceIteratorTests.cc @@ -171,6 +171,25 @@ TEST(1) x = collect_with_copy(i2o, g); EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0"); + db::Region r; + r.insert (db::Box (-600, -100, -500, 0)); + r.insert (db::Box (1600, 0, 1700, 100)); + db::RecursiveInstanceIterator i2r (g, c0, r); + db::RecursiveInstanceIterator i2rc = i2r; + x = collect(i2r, g); + EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0"); + x = collect_with_copy(i2r, g); + EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0"); + x = collect(i2rc, g); + EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0"); + x = collect_with_copy(i2rc, g); + EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0"); + db::RecursiveInstanceIterator i2ro (g, c0, r, true); + x = collect(i2ro, g); + EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100"); + x = collect_with_copy(i2ro, g); + EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100"); + db::RecursiveInstanceIterator i4 (g, c0, db::Box (-100, 0, 2000, 100)); db::RecursiveInstanceIterator i4_copy (g, c0, db::Box (-100, 0, 2000, 100)); i4.max_depth (0); @@ -252,17 +271,17 @@ TEST(1) EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0"); db::RecursiveInstanceIterator i1z (g, c0); - EXPECT_EQ (i1z.has_all_targets (), true); + EXPECT_EQ (i1z.all_targets_enabled (), true); std::set ct; ct.insert (c3.cell_index ()); - i1z.targets (ct); - EXPECT_EQ (i1z.has_all_targets (), false); + i1z.set_targets (ct); + EXPECT_EQ (i1z.all_targets_enabled (), false); EXPECT_EQ (i1z.targets () == ct, true); - i1z.all_targets (); - EXPECT_EQ (i1z.has_all_targets (), true); + i1z.enable_all_targets (); + EXPECT_EQ (i1z.all_targets_enabled (), true); - i1z.targets (ct); - EXPECT_EQ (i1z.has_all_targets (), false); + i1z.set_targets (ct); + EXPECT_EQ (i1z.all_targets_enabled (), false); x = collect(i1z, g); EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$4 r90 0,0"); @@ -270,393 +289,6 @@ TEST(1) EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$4 r90 0,0"); } -#if 0 -TEST(1a) -{ - db::Manager m (true); - db::Layout g (&m); - g.insert_layer (0); - g.insert_layer (1); - 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); - c1.shapes (0).insert (b); - c2.shapes (0).insert (b); - c3.shapes (0).insert (b); - - db::Box bb (1, 101, 1001, 1201); - c2.shapes (1).insert (bb); - - 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 i0 (g, c0, 0, db::Box ()); - x = collect_with_copy(i0, g); - EXPECT_EQ (x, ""); - x = collect(i0, g); - EXPECT_EQ (x, ""); - - db::RecursiveInstanceIterator i1 (g, c0, 0, db::Box (0, 0, 100, 100)); - x = collect_with_copy(i1, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)"); - x = collect(i1, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)"); - - db::RecursiveInstanceIterator i1o (g, c0, 0, db::Box (0, 0, 100, 100), true); - x = collect_with_copy(i1o, g); - EXPECT_EQ (x, ""); - x = collect(i1o, g); - EXPECT_EQ (x, ""); - i1o = db::RecursiveInstanceIterator (g, c0, 0, db::Box (0, 0, 100, 101), true); - x = collect_with_copy(i1o, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)"); - x = collect(i1o, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)"); - i1o = db::RecursiveInstanceIterator (g, c0, 0, db::Box (0, 0, 101, 101), true); - x = collect_with_copy(i1o, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)"); - x = collect(i1o, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)"); - - db::RecursiveInstanceIterator i2 (g, c0, 0, db::Box (-100, 0, 100, 100)); - x = collect_with_copy(i2, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](-1200,0;-100,1000)"); - x = collect(i2, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](-1200,0;-100,1000)"); - db::RecursiveInstanceIterator i2o (g, c0, 0, db::Box (-100, 0, 100, 100), true); - x = collect_with_copy(i2o, g); - EXPECT_EQ (x, ""); - x = collect(i2o, g); - EXPECT_EQ (x, ""); - i2o = db::RecursiveInstanceIterator (g, c0, 0, db::Box (-101, 0, 101, 101), true); - x = collect_with_copy(i2o, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](-1200,0;-100,1000)"); - x = collect(i2o, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](-1200,0;-100,1000)"); - - db::RecursiveInstanceIterator i4 (g, c0, 0, db::Box (-100, 0, 2000, 100)); - db::RecursiveInstanceIterator i4_copy (g, c0, 0, db::Box (-100, 0, 2000, 100)); - i4.max_depth (0); - x = collect_with_copy(i4, g); - EXPECT_EQ (x, ""); - x = collect(i4, g); - EXPECT_EQ (x, ""); - - EXPECT_EQ (i4 == i4, true); - EXPECT_EQ (i4 != i4, false); - EXPECT_EQ (i4 == i4_copy, false); - EXPECT_EQ (i4 != i4_copy, true); - i4 = i4_copy; - EXPECT_EQ (i4 == i4_copy, true); - EXPECT_EQ (i4 != i4_copy, false); - i4.max_depth (1); - x = collect_with_copy(i4, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](-1200,0;-100,1000)"); - x = collect(i4, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](-1200,0;-100,1000)"); - - i4 = i4_copy; - x = collect_with_copy(i4, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](1200,0;2200,1100)/[$4](-1200,0;-100,1000)"); - x = collect(i4, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](1200,0;2200,1100)/[$4](-1200,0;-100,1000)"); - - db::RecursiveInstanceIterator i5 (g, c0, 0, db::Box::world ()); - x = collect_with_copy(i5, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](1200,0;2200,1100)/[$4](-1200,0;-100,1000)"); - x = collect(i5, g); - EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)/[$4](1200,0;2200,1100)/[$4](-1200,0;-100,1000)"); - - i5.set_layer (1); - x = collect_with_copy(i5, g); - EXPECT_EQ (x, "[$3](101,1;1101,1101)"); - x = collect(i5, g); - EXPECT_EQ (x, "[$3](101,1;1101,1101)"); - - std::set ll; - - db::RecursiveInstanceIterator i5a (g, c0, ll, db::Box::world ()); - x = collect_with_copy(i5a, g, true); - EXPECT_EQ (x, ""); - x = collect(i5a, g, true); - EXPECT_EQ (x, ""); - - ll.insert (0); - db::RecursiveInstanceIterator i5b (g, c0, ll, db::Box::world ()); - x = collect_with_copy(i5b, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - x = collect(i5b, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - - ll.insert (1); - db::RecursiveInstanceIterator i5c (g, c0, ll, db::Box::world ()); - db::RecursiveInstanceIterator i5cc = i5c; - x = collect_with_copy(i5c, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$3](101,1;1101,1101)*1/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - x = collect(i5c, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$3](101,1;1101,1101)*1/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - x = collect_with_copy(i5cc, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$3](101,1;1101,1101)*1/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - x = collect(i5cc, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$3](101,1;1101,1101)*1/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - - std::vector ll_new; - ll_new.push_back (0); - i5c.set_layers (ll_new); - x = collect_with_copy(i5c, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); - x = collect(i5c, g, true); - EXPECT_EQ (x, "[$2](0,100;1000,1200)*0/[$3](100,0;1100,1100)*0/[$4](1200,0;2200,1100)*0/[$4](-1200,0;-100,1000)*0"); -} - -TEST(1b) -{ - db::Manager m (true); - db::Layout g (&m); - g.insert_layer (0); - db::Cell &c0 (g.cell (g.add_cell ())); - db::Cell &c1 (g.cell (g.add_cell ())); - - db::Box b; - b = db::Box (0, 0, 2000, 2000000); - c1.shapes (0).insert (b); - b = db::Box (1998000, 0, 2000000, 2000000); - c1.shapes (0).insert (b); - b = db::Box (0, 0, 2000000, 2000); - c1.shapes (0).insert (b); - b = db::Box (0, 1998000, 2000000, 2000000); - 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 ()), tt)); - - db::RecursiveInstanceIterator i (g, c0, 0, db::Box (1000000, 1000000, 10001000, 10001000)); - std::string x; - x = collect_with_copy(i, g); - EXPECT_EQ (x, "[$2](1998000,0;2000000,2000000)/[$2](0,1998000;2000000,2000000)/[$2](1998000,0;2000000,2000000)/[$2](0,1998000;2000000,2000000)"); - x = collect(i, g); - EXPECT_EQ (x, "[$2](1998000,0;2000000,2000000)/[$2](0,1998000;2000000,2000000)/[$2](1998000,0;2000000,2000000)/[$2](0,1998000;2000000,2000000)"); - - db::RecursiveInstanceIterator i2 (g, c0, 0, db::Box (1000000, 1000000, 1001000, 1001000)); - x = collect_with_copy(i2, g); - EXPECT_EQ (x, ""); - x = collect(i2, g); - EXPECT_EQ (x, ""); -} - -TEST(2) -{ - db::Manager m (true); - db::Layout g (&m); - g.insert_layer(0); - - 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::Box b (1000, -500, 2000, 500); - c2.shapes (0).insert (b); - - db::Trans tt; - c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt, db::Vector (0, 6000), db::Vector (6000, 0), 2, 2)); - c1.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), tt, db::Vector (0, 2000), db::Vector (3000, 1000), 2, 2)); - - std::string x; - - db::RecursiveInstanceIterator i0 (g, c0, 0, db::Box ()); - x = collect(i0, g); - EXPECT_EQ (x, ""); - - db::RecursiveInstanceIterator i (g, c0, 0, db::Box::world ()); - x = collect_with_copy(i, g); - EXPECT_EQ (x, "[$3](1000,-500;2000,500)/[$3](1000,1500;2000,2500)/[$3](4000,500;5000,1500)/[$3](4000,2500;5000,3500)/[$3](1000,5500;2000,6500)/[$3](1000,7500;2000,8500)/[$3](4000,6500;5000,7500)/[$3](4000,8500;5000,9500)/[$3](7000,-500;8000,500)/[$3](7000,1500;8000,2500)/[$3](10000,500;11000,1500)/[$3](10000,2500;11000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)/[$3](10000,8500;11000,9500)"); - x = collect(i, g); - EXPECT_EQ (x, "[$3](1000,-500;2000,500)/[$3](1000,1500;2000,2500)/[$3](4000,500;5000,1500)/[$3](4000,2500;5000,3500)/[$3](1000,5500;2000,6500)/[$3](1000,7500;2000,8500)/[$3](4000,6500;5000,7500)/[$3](4000,8500;5000,9500)/[$3](7000,-500;8000,500)/[$3](7000,1500;8000,2500)/[$3](10000,500;11000,1500)/[$3](10000,2500;11000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)/[$3](10000,8500;11000,9500)"); - - db::RecursiveInstanceIterator i2 (g, c0, 0, db::Box (3400, 3450, 5600, 6500)); - x = collect_with_copy(i2, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)"); - x = collect(i2, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)"); - - db::RecursiveInstanceIterator i3 (g, c0, 0, db::Box (6650, 5300, 10000, 7850)); - x = collect_with_copy(i3, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)"); - x = collect(i3, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)"); - - db::RecursiveInstanceIterator i2o (g, c0, 0, db::Box (3400, 3450, 5600, 6500), true); - x = collect_with_copy(i2o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - x = collect(i2o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - - db::RecursiveInstanceIterator i3o (g, c0, 0, db::Box (6650, 5300, 10000, 7850), true); - x = collect_with_copy(i3o, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect(i3o, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); -} - -TEST(3) -{ - db::Manager m (true); - db::Layout g (&m); - g.insert_layer(0); - - 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::Box b (1000, -500, 2000, 500); - c2.shapes (0).insert (b); - - db::Trans tt; - c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt, db::Vector (0, 6000), db::Vector (6000, 0), 2, 2)); - c1.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), tt, db::Vector (0, 2000), db::Vector (3000, 1000), 2, 2)); - - std::string x; - - db::RecursiveInstanceIterator i (g, c0, 0, db::Box::world ()); - x = collect_with_copy(i, g); - EXPECT_EQ (x, "[$3](1000,-500;2000,500)/[$3](1000,1500;2000,2500)/[$3](4000,500;5000,1500)/[$3](4000,2500;5000,3500)/[$3](1000,5500;2000,6500)/[$3](1000,7500;2000,8500)/[$3](4000,6500;5000,7500)/[$3](4000,8500;5000,9500)/[$3](7000,-500;8000,500)/[$3](7000,1500;8000,2500)/[$3](10000,500;11000,1500)/[$3](10000,2500;11000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)/[$3](10000,8500;11000,9500)"); - x = collect(i, g); - EXPECT_EQ (x, "[$3](1000,-500;2000,500)/[$3](1000,1500;2000,2500)/[$3](4000,500;5000,1500)/[$3](4000,2500;5000,3500)/[$3](1000,5500;2000,6500)/[$3](1000,7500;2000,8500)/[$3](4000,6500;5000,7500)/[$3](4000,8500;5000,9500)/[$3](7000,-500;8000,500)/[$3](7000,1500;8000,2500)/[$3](10000,500;11000,1500)/[$3](10000,2500;11000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)/[$3](10000,8500;11000,9500)"); - - db::RecursiveInstanceIterator i2 (g, c0, 0, db::Region (db::Box (3400, 3450, 5600, 6500))); - EXPECT_EQ (i2.has_complex_region (), false); - EXPECT_EQ (i2.region ().to_string (), "(3400,3450;5600,6500)"); - x = collect_with_copy(i2, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)"); - x = collect(i2, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)"); - - db::RecursiveInstanceIterator i3 (g, c0, 0, db::Region (db::Box (6650, 5300, 10000, 7850))); - x = collect_with_copy(i3, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)"); - x = collect(i3, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)"); - - db::Region rr; - rr.insert (db::Box (3400, 3450, 5600, 6500)); - rr.insert (db::Box (6650, 5300, 10000, 7850)); - - db::RecursiveInstanceIterator i23 (g, c0, 0, rr); - x = collect_with_copy(i23, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)"); - x = collect(i23, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)"); - - db::RecursiveInstanceIterator i2o (g, c0, 0, db::Region (db::Box (3400, 3450, 5600, 6500)), true); - x = collect_with_copy(i2o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - x = collect(i2o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - - db::RecursiveInstanceIterator i3o (g, c0, 0, db::Region (db::Box (6650, 5300, 10000, 7850)), true); - x = collect_with_copy(i3o, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect(i3o, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - - db::Region rro; - rro.insert (db::Box (3400, 3450, 5600, 6500)); - rro.insert (db::Box (6650, 5300, 10000, 7850)); - - db::RecursiveInstanceIterator i23o (g, c0, 0, rro, true); - EXPECT_EQ (i23o.has_complex_region (), true); - EXPECT_EQ (i23o.complex_region ().to_string (), "(3400,3450;3400,6500;5600,6500;5600,3450);(6650,5300;6650,7850;10000,7850;10000,5300)"); - - db::RecursiveInstanceIterator i23ocopy = i23o; - - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - - x = collect_with_copy (i23ocopy, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect (i23ocopy, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - - // reset - i23o.reset (); - x = collect_with_copy (i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect (i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - - // copy constructor - i23ocopy = i23o; - i23ocopy.reset (); - x = collect_with_copy (i23ocopy, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect (i23ocopy, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - - // setting of region - - db::Region rg; - i23o.set_region (rg); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, ""); - x = collect(i23o, g); - EXPECT_EQ (x, ""); - - rg.insert (db::Box (3400, 3450, 5600, 6500)); - rg.insert (db::Box (16650, 5300, 20000, 7850)); - - i23o.set_region (rg); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - x = collect(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - - i23o.set_region (db::Box (6650, 5300, 10000, 7850)); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect(i23o, g); - EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - - // region confinement - - i23o.confine_region (db::Box (3400, 3450, 5600, 6500)); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, ""); - x = collect(i23o, g); - EXPECT_EQ (x, ""); - - i23o.set_region (rro); - i23o.confine_region (db::Box (3400, 3450, 5600, 6500)); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - x = collect(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - - i23o.set_region (db::Box (3400, 3450, 5600, 6500)); - i23o.confine_region (rro); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - x = collect(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)"); - - i23o.set_region (rro); - i23o.confine_region (rro); - x = collect_with_copy(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); - x = collect(i23o, g); - EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)"); -} - static db::Layout boxes2layout (const std::set &boxes) { db::Layout l; @@ -671,106 +303,21 @@ static db::Layout boxes2layout (const std::set &boxes) } class FlatPusher - : public db::RecursiveShapeReceiver + : public db::RecursiveInstanceReceiver { public: FlatPusher (std::set *boxes) : mp_boxes (boxes) { } - void shape (const db::RecursiveInstanceIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) + void enter_cell (const db::RecursiveInstanceIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { - mp_boxes->insert (trans * shape.bbox ()); + mp_boxes->insert (iter->trans () * cell->bbox ()); } private: std::set *mp_boxes; }; -TEST(4) -{ - // Big fun - - db::Manager m (true); - db::Layout g (&m); - g.insert_layer(0); - - db::Cell &c0 (g.cell (g.add_cell ())); - - std::set boxes; - - for (int i = 0; i < 100000; ++i) { - - int x = rand () % 10000; - int y = rand () % 10000; - db::Box box (x, y, x + 10, y + 10); - - boxes.insert (box); - - c0.shapes (0).insert (box); - - } - - db::Box search_box (2500, 2500, 7500, 7500); - - std::set selected_boxes; - std::set selected_boxes2; - - for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, 0, search_box, true); !iter.at_end (); ++iter) { - selected_boxes.insert (iter->bbox ()); - } - - for (std::set::const_iterator b = boxes.begin (); b != boxes.end (); ++b) { - if (search_box.overlaps (*b)) { - selected_boxes2.insert (*b); - } - } - - EXPECT_EQ (selected_boxes.size () > 100, true); - EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); - - // push mode - { - selected_boxes.clear (); - FlatPusher pusher (&selected_boxes); - db::RecursiveInstanceIterator (g, c0, 0, search_box, true).push (&pusher); - } - - EXPECT_EQ (selected_boxes.size () > 100, true); - EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); - - db::Box search_box2 (500, 500, 1000, 1000); - - selected_boxes.clear (); - selected_boxes2.clear (); - - db::Region reg; - reg.insert (search_box); - reg.insert (search_box2); - - for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, 0, reg, true); !iter.at_end (); ++iter) { - selected_boxes.insert (iter->bbox ()); - } - - for (std::set::const_iterator b = boxes.begin (); b != boxes.end (); ++b) { - if (search_box.overlaps (*b) || search_box2.overlaps (*b)) { - selected_boxes2.insert (*b); - } - } - - EXPECT_EQ (selected_boxes.size () > 100, true); - EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); - - // push mode - { - selected_boxes.clear (); - FlatPusher pusher (&selected_boxes); - db::RecursiveInstanceIterator (g, c0, 0, reg, true).push (&pusher); - } - - EXPECT_EQ (selected_boxes.size () > 100, true); - EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); -} - -TEST(5) +TEST(2) { // Big fun with cells @@ -802,7 +349,7 @@ TEST(5) std::set selected_boxes; std::set selected_boxes2; - for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, 0, search_box, true); !iter.at_end (); ++iter) { + for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true); !iter.at_end (); ++iter) { selected_boxes.insert (iter.trans () * iter->bbox ()); } @@ -819,7 +366,7 @@ TEST(5) { selected_boxes.clear (); FlatPusher pusher (&selected_boxes); - db::RecursiveInstanceIterator (g, c0, 0, search_box, true).push (&pusher); + db::RecursiveInstanceIterator (g, c0, search_box, true).push (&pusher); } EXPECT_EQ (selected_boxes.size () > 100, true); @@ -834,7 +381,7 @@ TEST(5) reg.insert (search_box); reg.insert (search_box2); - for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, 0, reg, true); !iter.at_end (); ++iter) { + for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) { selected_boxes.insert (iter.trans () * iter->bbox ()); } @@ -851,115 +398,17 @@ TEST(5) { selected_boxes.clear (); FlatPusher pusher (&selected_boxes); - db::RecursiveInstanceIterator (g, c0, 0, reg, true).push (&pusher); + db::RecursiveInstanceIterator (g, c0, reg, true).push (&pusher); } EXPECT_EQ (selected_boxes.size () > 100, true); EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); } -class LoggingReceiver - : public db::RecursiveShapeReceiver +TEST(3) { -public: - LoggingReceiver () { } + // Big fun with cells - 2 hierarchy levels - const std::string &text () const { return m_text; } - - virtual void begin (const db::RecursiveInstanceIterator * /*iter*/) { m_text += "begin\n"; } - virtual void end (const db::RecursiveInstanceIterator * /*iter*/) { m_text += "end\n"; } - - virtual void enter_cell (const db::RecursiveInstanceIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) - { - m_text += std::string ("enter_cell(") + iter->layout ()->cell_name (cell->cell_index ()) + ")\n"; - } - - virtual void leave_cell (const db::RecursiveInstanceIterator *iter, const db::Cell *cell) - { - m_text += std::string ("leave_cell(") + iter->layout ()->cell_name (cell->cell_index ()) + ")\n"; - } - - virtual new_inst_mode new_inst (const db::RecursiveInstanceIterator *iter, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all) - { - m_text += std::string ("new_inst(") + iter->layout ()->cell_name (inst.object ().cell_index ()); - if (all) { - m_text += ",all"; - } - m_text += ")\n"; - return NI_all; - } - - virtual bool new_inst_member (const db::RecursiveInstanceIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all) - { - m_text += std::string ("new_inst_member(") + iter->layout ()->cell_name (inst.object ().cell_index ()) + "," + tl::to_string (trans); - if (all) { - m_text += ",all"; - } - m_text += ")\n"; - return true; - } - - virtual void shape (const db::RecursiveInstanceIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) - { - m_text += "shape(" + shape.to_string () + "," + tl::to_string (trans) + ")\n"; - } - -private: - std::string m_text; -}; - -class ReceiverRejectingACellInstanceArray - : public LoggingReceiver -{ -public: - ReceiverRejectingACellInstanceArray (db::cell_index_type rejected) : m_rejected (rejected) { } - - virtual new_inst_mode new_inst (const db::RecursiveInstanceIterator *iter, const db::CellInstArray &inst, const db::Box ®ion, const box_tree_type *complex_region, bool all) - { - LoggingReceiver::new_inst (iter, inst, region, complex_region, all); - return inst.object ().cell_index () != m_rejected ? NI_all : NI_skip; - } - -private: - db::cell_index_type m_rejected; -}; - -class ReceiverRejectingACellInstanceArrayExceptOne - : public LoggingReceiver -{ -public: - ReceiverRejectingACellInstanceArrayExceptOne (db::cell_index_type rejected) : m_rejected (rejected) { } - - virtual new_inst_mode new_inst (const db::RecursiveInstanceIterator *iter, const db::CellInstArray &inst, const db::Box ®ion, const box_tree_type *complex_region, bool all) - { - LoggingReceiver::new_inst (iter, inst, region, complex_region, all); - return inst.object ().cell_index () != m_rejected ? NI_all : NI_single; - } - -private: - db::cell_index_type m_rejected; -}; - -class ReceiverRejectingACellInstance - : public LoggingReceiver -{ -public: - ReceiverRejectingACellInstance (db::cell_index_type rejected, const db::ICplxTrans &trans_rejected) : m_rejected (rejected), m_trans_rejected (trans_rejected) { } - - virtual bool new_inst_member (const db::RecursiveInstanceIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box ®ion, const box_tree_type *complex_region, bool all) - { - LoggingReceiver::new_inst_member (iter, inst, trans, region, complex_region, all); - return inst.object ().cell_index () != m_rejected || trans != m_trans_rejected; - } - -private: - db::cell_index_type m_rejected; - db::ICplxTrans m_trans_rejected; -}; - -// Push mode with cells -TEST(10) -{ db::Manager m (true); db::Layout g (&m); g.insert_layer(0); @@ -968,302 +417,201 @@ TEST(10) db::Cell &c1 (g.cell (g.add_cell ())); db::Cell &c2 (g.cell (g.add_cell ())); - db::Box b (1000, -500, 2000, 500); - c2.shapes (0).insert (b); - c0.shapes (0).insert (b.moved (db::Vector (-1000, 500))); - c0.shapes (0).insert (b.moved (db::Vector (-2000, 500))); + db::Box basic_box (0, 0, 10, 10); + c2.shapes (0).insert (basic_box); + c1.insert (db::CellInstArray (c2.cell_index (), db::Trans (db::Vector (1, -1)))); - db::Trans tt; - c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt, db::Vector (0, 6000), db::Vector (6000, 0), 2, 2)); - c1.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), tt, db::Vector (0, 2000), db::Vector (3000, 1000), 2, 2)); + std::set boxes; - LoggingReceiver lr1; - db::RecursiveInstanceIterator i1 (g, c0, 0); - i1.push (&lr1); + int nboxes = 100000; + for (int i = 0; i < nboxes; ++i) { - EXPECT_EQ (lr1.text (), - "begin\n" - "new_inst($2,all)\n" - "new_inst_member($2,r0 *1 0,0,all)\n" - // It's a bit weird to have shape events after new_inst_member, but remember, new_inst_member is a query callback, not an event. - "shape(box (0,0;1000,1000),r0 *1 0,0)\n" - "shape(box (-1000,0;0,1000),r0 *1 0,0)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,0)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,2000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,1000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,3000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 0,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,6000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,8000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,7000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,9000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,0,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,0)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,2000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,1000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,3000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,6000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,8000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,7000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,9000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "end\n" - ); + int x, y; - ReceiverRejectingACellInstanceArray rr1 (c2.cell_index ()); - db::RecursiveInstanceIterator ir1 (g, c0, 0); - ir1.push (&rr1); + do { + x = rand () % 10000; + y = rand () % 10000; + } while (boxes.find (basic_box.moved (db::Vector (x + 1, y - 1))) != boxes.end ()); - EXPECT_EQ (rr1.text (), - "begin\n" - "new_inst($2,all)\n" - "new_inst_member($2,r0 *1 0,0,all)\n" - "shape(box (0,0;1000,1000),r0 *1 0,0)\n" - "shape(box (-1000,0;0,1000),r0 *1 0,0)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 0,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,0,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "leave_cell($2)\n" - "end\n" - ); + boxes.insert (basic_box.moved (db::Vector (x + 1, y - 1))); - ReceiverRejectingACellInstanceArrayExceptOne rs1 (c2.cell_index ()); - db::RecursiveInstanceIterator is1 (g, c0, 0); - is1.push (&rs1); + c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y)))); - EXPECT_EQ (rs1.text (), - "begin\n" - "new_inst($2,all)\n" - "new_inst_member($2,r0 *1 0,0,all)\n" - "shape(box (0,0;1000,1000),r0 *1 0,0)\n" - "shape(box (-1000,0;0,1000),r0 *1 0,0)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,0)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 0,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,6000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,0,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,0)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,6000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "end\n" - ); + } - ReceiverRejectingACellInstance rri1 (c2.cell_index (), db::ICplxTrans ()); - db::RecursiveInstanceIterator iri1 (g, c0, 0); - iri1.push (&rri1); + db::Box search_box (2500, 2500, 7500, 7500); - EXPECT_EQ (rri1.text (), - "begin\n" - "new_inst($2,all)\n" - "new_inst_member($2,r0 *1 0,0,all)\n" - "shape(box (0,0;1000,1000),r0 *1 0,0)\n" - "shape(box (-1000,0;0,1000),r0 *1 0,0)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" // -> skipped - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,2000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,1000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,3000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 0,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,8000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,7000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,9000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,0,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,2000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,1000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,3000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "new_inst_member($2,r0 *1 6000,6000,all)\n" - "enter_cell($2)\n" - "new_inst($3,all)\n" - "new_inst_member($3,r0 *1 0,0,all)\n" - "new_inst_member($3,r0 *1 0,2000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 6000,8000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,7000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000,all)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 9000,9000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "end\n" - ); + std::set selected_boxes; + std::set selected_boxes2; - ReceiverRejectingACellInstanceArray rr2 (c1.cell_index ()); - db::RecursiveInstanceIterator ir2 (g, c0, 0); - ir2.push (&rr2); + db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true); + std::set tc; + tc.insert (c2.cell_index ()); + iter.set_targets (tc); + int n = 0; + for ( ; !iter.at_end (); ++iter) { + ++n; + selected_boxes.insert (iter.trans () * iter->bbox ()); + } - EXPECT_EQ (rr2.text (), - "begin\n" - "new_inst($2,all)\n" - "shape(box (0,0;1000,1000),r0 *1 0,0)\n" - "shape(box (-1000,0;0,1000),r0 *1 0,0)\n" - "end\n" - ); + int nn = 0; + for (std::set::const_iterator b = boxes.begin (); b != boxes.end (); ++b) { + if (search_box.overlaps (*b)) { + ++nn; + selected_boxes2.insert (*b); + } + } - LoggingReceiver lr2; - db::RecursiveInstanceIterator i2 (g, c0, 0, db::Box (0, 0, 5000, 5000)); - i2.push (&lr2); + EXPECT_EQ (n, nn); - EXPECT_EQ (lr2.text (), - "begin\n" - "new_inst($2)\n" - "new_inst_member($2,r0 *1 0,0)\n" - "shape(box (0,0;1000,1000),r0 *1 0,0)\n" - "shape(box (-1000,0;0,1000),r0 *1 0,0)\n" - "enter_cell($2)\n" - "new_inst($3)\n" - "new_inst_member($3,r0 *1 0,0)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,0)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 0,2000)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 0,2000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,1000)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,1000)\n" - "leave_cell($3)\n" - "new_inst_member($3,r0 *1 3000,3000)\n" - "enter_cell($3)\n" - "shape(box (1000,-500;2000,500),r0 *1 3000,3000)\n" - "leave_cell($3)\n" - "leave_cell($2)\n" - "end\n" - ); + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); + + // push mode + { + selected_boxes.clear (); + FlatPusher pusher (&selected_boxes); + db::RecursiveInstanceIterator (g, c0, search_box, true).push (&pusher); + } + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); + + db::Box search_box2 (500, 500, 1000, 1000); + + selected_boxes.clear (); + selected_boxes2.clear (); + + db::Region reg; + reg.insert (search_box); + reg.insert (search_box2); + + for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) { + selected_boxes.insert (iter.trans () * iter->bbox ()); + } + + for (std::set::const_iterator b = boxes.begin (); b != boxes.end (); ++b) { + if (search_box.overlaps (*b) || search_box2.overlaps (*b)) { + selected_boxes2.insert (*b); + } + } + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); + + // push mode + { + selected_boxes.clear (); + FlatPusher pusher (&selected_boxes); + db::RecursiveInstanceIterator (g, c0, reg, true).push (&pusher); + } + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); } -#endif + +TEST(4) +{ + // Big fun with cells - 2 hierarchy levels + touching mode + + db::Manager m (true); + db::Layout g (&m); + g.insert_layer(0); + + 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::Box basic_box (0, 0, 10, 10); + c2.shapes (0).insert (basic_box); + c1.insert (db::CellInstArray (c2.cell_index (), db::Trans (db::Vector (1, -1)))); + + std::set boxes; + + int nboxes = 100000; + for (int i = 0; i < nboxes; ++i) { + + int x, y; + + do { + x = rand () % 10000; + y = rand () % 10000; + } while (boxes.find (basic_box.moved (db::Vector (x + 1, y - 1))) != boxes.end ()); + + boxes.insert (basic_box.moved (db::Vector (x + 1, y - 1))); + + c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y)))); + + } + + db::Box search_box (2500, 2500, 7500, 7500); + + std::set selected_boxes; + std::set selected_boxes2; + + db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box); + std::set tc; + tc.insert (c2.cell_index ()); + iter.set_targets (tc); + int n = 0; + for ( ; !iter.at_end (); ++iter) { + ++n; + selected_boxes.insert (iter.trans () * iter->bbox ()); + } + + int nn = 0; + for (std::set::const_iterator b = boxes.begin (); b != boxes.end (); ++b) { + if (search_box.touches (*b)) { + ++nn; + selected_boxes2.insert (*b); + } + } + + EXPECT_EQ (n, nn); + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); + + // push mode + { + selected_boxes.clear (); + FlatPusher pusher (&selected_boxes); + db::RecursiveInstanceIterator (g, c0, search_box).push (&pusher); + } + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); + + db::Box search_box2 (500, 500, 1000, 1000); + + selected_boxes.clear (); + selected_boxes2.clear (); + + db::Region reg; + reg.insert (search_box); + reg.insert (search_box2); + + for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg); !iter.at_end (); ++iter) { + selected_boxes.insert (iter.trans () * iter->bbox ()); + } + + for (std::set::const_iterator b = boxes.begin (); b != boxes.end (); ++b) { + if (search_box.touches (*b) || search_box2.touches (*b)) { + selected_boxes2.insert (*b); + } + } + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); + + // push mode + { + selected_boxes.clear (); + FlatPusher pusher (&selected_boxes); + db::RecursiveInstanceIterator (g, c0, reg).push (&pusher); + } + + EXPECT_EQ (selected_boxes.size () > 100, true); + EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true); +} +