diff --git a/src/db/db/dbCell.cc b/src/db/db/dbCell.cc index 346f3d8ab..906752112 100644 --- a/src/db/db/dbCell.cc +++ b/src/db/db/dbCell.cc @@ -487,6 +487,41 @@ Cell::hierarchy_levels () const return m_hier_levels; } +static bool +has_shapes_touching_impl (const db::Cell &cell, unsigned int layer, const db::Box &box) +{ + if (! cell.shapes (layer).begin_touching (box, db::ShapeIterator::All).at_end ()) { + return true; + } + + for (db::Cell::touching_iterator i = cell.begin_touching (box); ! i.at_end (); ++i) { + + for (db::CellInstArray::iterator ia = i->cell_inst ().begin_touching (box, db::box_convert (*cell.layout (), layer)); ! ia.at_end (); ++ia) { + + db::Box cbox; + if (i->is_complex ()) { + cbox = i->complex_trans (*ia).inverted () * box; + } else { + cbox = (*ia).inverted () * box; + } + + if (has_shapes_touching_impl (cell.layout ()->cell (i->cell_index ()), layer, cbox)) { + return true; + } + + } + + } + + return false; +} + +bool +Cell::has_shapes_touching (unsigned int layer, const db::Box &box) const +{ + return has_shapes_touching_impl (*this, layer, box); +} + void Cell::collect_caller_cells (std::set &callers) const { diff --git a/src/db/db/dbCell.h b/src/db/db/dbCell.h index b20803953..db7089b2a 100644 --- a/src/db/db/dbCell.h +++ b/src/db/db/dbCell.h @@ -721,6 +721,11 @@ public: return shapes (layer).begin_touching (box, flags, prop_sel, inv_prop_sel); } + /** + * @brief A quick, recursive test whether the cell has shapes touching the given box on the given layer + */ + bool has_shapes_touching (unsigned int layer, const db::Box &box) const; + /** * @brief Collect all calling cells (either calling this cell directly or indirectly) * diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 3b589f420..1bb829fd8 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1104,7 +1104,7 @@ printf("@@@ -> #%d\n", int(inst1->size())); db::Box ibox2 = tn2 * cell2.bbox (m_intruder_layer).enlarged (db::Vector (m_dist, m_dist)); db::Box cbox = ibox1 & ibox2; - if (! cbox.empty () && ! db::RecursiveShapeIterator (*mp_subject_layout, cell1, m_subject_layer, safe_box_enlarged (tni1 * cbox, -1, -1), false).at_end ()) { + if (! cbox.empty () && cell1.has_shapes_touching (m_subject_layer, safe_box_enlarged (tni1 * cbox, -1, -1))) { db::ICplxTrans tn21 = tni1 * tn2; @@ -1151,14 +1151,14 @@ printf("@@@ -> #%d\n", int(inst1->size())); const db::Cell &ic = mp_intruder_layout->cell (i->cell_index ()); - for (db::CellInstArray::iterator ia = i->begin_touching (tbox2, mp_intruder_layout); ! ia.at_end (); ++ia) { + for (db::CellInstArray::iterator ia = i->cell_inst ().begin_touching (tbox2, db::box_convert (*mp_intruder_layout, m_intruder_layer)); ! ia.at_end (); ++ia) { db::ICplxTrans it = i->complex_trans (*ia); db::Box ibox2 = tni2.inverted () * it * ic.bbox (m_intruder_layer).enlarged (db::Vector (m_dist, m_dist)); db::Box ccbox = cbox & ibox2; - if (! ccbox.empty () && ! db::RecursiveShapeIterator (*mp_subject_layout, subject_cell, m_subject_layer, safe_box_enlarged (tni1 * ccbox, -1, -1), false).at_end ()) { + if (! ccbox.empty ()) { collect_intruder_tree_interactions (subject_cell, ic, tni1, tn21 * it, ccbox, interactions); } diff --git a/src/db/unit_tests/dbCellTests.cc b/src/db/unit_tests/dbCellTests.cc index 448583d81..6578dea84 100644 --- a/src/db/unit_tests/dbCellTests.cc +++ b/src/db/unit_tests/dbCellTests.cc @@ -1014,3 +1014,49 @@ TEST(6) } +TEST(10_HasShapesTouching) +{ + db::Layout ly; + unsigned int l1 = ly.insert_layer (db::LayerProperties (1, 0)); + + db::Cell &a = ly.cell (ly.add_cell ("A")); + + EXPECT_EQ (a.has_shapes_touching (l1, db::Box ()), false); + + a.shapes (l1).insert (db::Box (-100, -100, 0, 0)); + + EXPECT_EQ (a.has_shapes_touching (l1, db::Box ()), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (0, 0, 100, 100)), true); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (0, 1, 100, 100)), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (0, -1, 100, 100)), true); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (-1, -1, -1, -1)), true); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (1, 1, 1, 1)), false); +} + +TEST(11_HasShapesTouchingWithHier) +{ + db::Layout ly; + unsigned int l1 = ly.insert_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.insert_layer (db::LayerProperties (2, 0)); + + db::Cell &a = ly.cell (ly.add_cell ("A")); + db::Cell &b = ly.cell (ly.add_cell ("B")); + + a.insert (db::CellInstArray (b.cell_index (), db::Trans (db::Vector (100, 100)), db::Vector (0, 200), db::Vector (200, 0), 2, 2)); + + EXPECT_EQ (a.has_shapes_touching (l1, db::Box ()), false); + EXPECT_EQ (a.has_shapes_touching (l2, db::Box ()), false); + + b.shapes (l1).insert (db::Box (0, 0, 10, 10)); + + EXPECT_EQ (a.has_shapes_touching (l1, db::Box ()), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (0, 0, 100, 100)), true); + EXPECT_EQ (a.has_shapes_touching (l2, db::Box (0, 0, 100, 100)), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (0, 0, 99, 100)), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (0, 0, 100, 99)), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (100, 100, 110, 110)), true); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (150, 150, 160, 160)), false); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (300, 300, 310, 310)), true); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (300, 100, 310, 110)), true); + EXPECT_EQ (a.has_shapes_touching (l1, db::Box (300, 400, 310, 410)), false); +}