WIP: lean recursive shape touch check

This commit is contained in:
Matthias Koefferlein 2021-10-27 00:38:08 +02:00
parent 596080669d
commit 20f3733c58
4 changed files with 89 additions and 3 deletions

View File

@ -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<db::CellInst> (*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<cell_index_type> &callers) const
{

View File

@ -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)
*

View File

@ -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<db::CellInst> (*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);
}

View File

@ -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);
}