From 3df88ae279f1a8c2387bb07799e7981d60fc2d06 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 15 Feb 2026 19:17:21 +0100 Subject: [PATCH] A small, but sometimes effective optimization of DRC check functions: if a feature is entirely covered (with interaction distance) by a box, it is enough to check against the box --- src/db/db/dbRegionLocalOperations.cc | 40 +++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 6d0a20d60..274b1c334 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -232,6 +232,8 @@ check_local_operation_base::compute_results (db::Layout *layout, db::Cel bool take_all = edge_check.has_negative_edge_output () || intruders.empty (); db::Box common_box; + bool subjects_are_fully_covered = false; + if (! take_all) { db::Vector e (edge_check.distance (), edge_check.distance ()); @@ -241,14 +243,24 @@ check_local_operation_base::compute_results (db::Layout *layout, db::Cel subject_box += db::box_convert () (**i); } - if (edge_check.requires_different_layers ()) { - db::Box intruder_box; + common_box = subject_box.enlarged (e); + + if (edge_check.requires_different_layers () && ! common_box.empty ()) { + + subjects_are_fully_covered = false; + + db::Box all_intruders_box; + for (auto i = intruders.begin (); i != intruders.end (); ++i) { - intruder_box += db::box_convert () (**i); + db::Box intruder_box = db::box_convert () (**i); + if (! subjects_are_fully_covered && (*i)->is_box () && common_box.inside (intruder_box)) { + subjects_are_fully_covered = true; + } + all_intruders_box += intruder_box.enlarged (e); } - common_box = subject_box.enlarged (e) & intruder_box.enlarged (e); - } else { - common_box = subject_box.enlarged (e); + + common_box &= all_intruders_box; + } } @@ -306,6 +318,22 @@ check_local_operation_base::compute_results (db::Layout *layout, db::Cel // empty intruders + } else if (subjects_are_fully_covered) { + + // optimization: can use a single box for the intruders + + n = 1; + + db::Point ul = common_box.upper_left (); + db::Point lr = common_box.lower_right (); + + poly_check.enter (db::Edge (common_box.p1 (), ul), n); + poly_check.enter (db::Edge (ul, common_box.p2 ()), n); + poly_check.enter (db::Edge (common_box.p2 (), lr), n); + poly_check.enter (db::Edge (lr, common_box.p1 ()), n); + + n += 2; + } else if (! m_other_is_merged && (intruders.size () > 1 || ! (*intruders.begin ())->is_box ())) { // NOTE: this local merge is not necessarily giving the same results than a global merge before running