From d8f3c522c93c0ce22aa6273c1154e15b6bb7bec6 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 25 Jun 2022 20:02:15 +0200 Subject: [PATCH 1/9] Removed a performance bottleneck (do not invalidate cache that often of inst to shape interaction computation) --- src/db/db/dbHierProcessor.cc | 38 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 87ca8a900..fc96f6cd9 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -189,12 +189,19 @@ public: typedef typename Ref::shape_type shape_type; typedef typename Ref::trans_type ref_trans_type; - shape_reference_translator_with_trans_from_shape_ref (db::Layout *target_layout, const Trans &trans) - : mp_layout (target_layout), m_trans (trans), m_ref_trans (trans), m_bare_trans (Trans (m_ref_trans.inverted ()) * trans) + shape_reference_translator_with_trans_from_shape_ref (db::Layout *target_layout) + : mp_layout (target_layout) { // .. nothing yet .. } + void set_trans (const Trans &trans) + { + m_trans = trans; + m_ref_trans = ref_trans_type (trans); + m_bare_trans = Trans (m_ref_trans.inverted ()) * trans; + } + Ref operator() (const Ref &ref) const { typename std::unordered_map >::const_iterator m = m_cache.find (ref.ptr ()); @@ -234,8 +241,8 @@ class shape_reference_translator_with_trans : public shape_reference_translator_with_trans_from_shape_ref { public: - shape_reference_translator_with_trans (db::Layout *target_layout, const Trans &trans) - : shape_reference_translator_with_trans_from_shape_ref (target_layout, trans) + shape_reference_translator_with_trans (db::Layout *target_layout) + : shape_reference_translator_with_trans_from_shape_ref (target_layout) { // .. nothing yet .. } @@ -247,12 +254,16 @@ class shape_reference_translator_with_trans public: typedef Sh shape_type; - shape_reference_translator_with_trans (db::Layout * /*target_layout*/, const Trans &trans) - : m_trans (trans) + shape_reference_translator_with_trans (db::Layout * /*target_layout*/) { // .. nothing yet .. } + void set_trans (const Trans &trans) + { + m_trans = trans; + } + shape_type operator() (const shape_type &s) const { return s.transformed (m_trans); @@ -353,13 +364,20 @@ local_processor_cell_context::propagate (unsigned int output_layer, return; } + db::Layout *subject_layout = 0; + shape_reference_translator_with_trans rt (subject_layout); + for (typename std::vector >::const_iterator d = m_drops.begin (); d != m_drops.end (); ++d) { tl_assert (d->parent_context != 0); tl_assert (d->parent != 0); - db::Layout *subject_layout = d->parent->layout (); - shape_reference_translator_with_trans rt (subject_layout, d->cell_inst); + if (subject_layout != d->parent->layout ()) { + subject_layout = d->parent->layout (); + rt = shape_reference_translator_with_trans (subject_layout); + } + + rt.set_trans (d->cell_inst); std::vector new_refs; new_refs.reserve (res.size ()); for (typename std::unordered_set::const_iterator r = res.begin (); r != res.end (); ++r) { @@ -1203,6 +1221,8 @@ private: db::box_convert inst_bc (*mp_subject_layout, m_subject_layer); db::Box rbox = db::box_convert () (ref); + db::shape_reference_translator_with_trans rt (mp_subject_layout); + for (db::CellInstArray::iterator n = inst->begin_touching (safe_box_enlarged (rbox, dist - 1, dist - 1), inst_bc); ! n.at_end (); ++n) { db::ICplxTrans tn = inst->complex_trans (*n); @@ -1211,7 +1231,7 @@ private: if (! cbox.empty ()) { db::ICplxTrans tni = tn.inverted (); - db::shape_reference_translator_with_trans rt (mp_subject_layout, tni); + rt.set_trans (tni); std::set *shapes = 0; From 959b5fe7997a9aed5c9e9f7b24402f6ef45dc09d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 25 Jun 2022 20:02:41 +0200 Subject: [PATCH 2/9] Faster hash of shape references (need to see what that is doing to test results) --- src/db/db/dbHash.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/db/db/dbHash.h b/src/db/db/dbHash.h index 6d511285b..59d9b882b 100644 --- a/src/db/db/dbHash.h +++ b/src/db/db/dbHash.h @@ -514,13 +514,13 @@ namespace std template size_t hfunc (const db::shape_ref &o, size_t h) { - return hfunc (*o.ptr (), hfunc (o.trans (), h)); + return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::shape_ref &o) { - return hfunc (*o.ptr (), hfunc (o.trans ())); + return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); } template @@ -539,13 +539,13 @@ namespace std template size_t hfunc (const db::polygon_ref &o, size_t h) { - return hfunc (*o.ptr (), hfunc (o.trans (), h)); + return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::polygon_ref &o) { - return hfunc (*o.ptr (), hfunc (o.trans ())); + return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); } template @@ -564,13 +564,13 @@ namespace std template size_t hfunc (const db::path_ref &o, size_t h) { - return hfunc (*o.ptr (), hfunc (o.trans (), h)); + return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::path_ref &o) { - return hfunc (*o.ptr (), hfunc (o.trans ())); + return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); } template @@ -589,13 +589,13 @@ namespace std template size_t hfunc (const db::text_ref &o, size_t h) { - return hfunc (*o.ptr (), hfunc (o.trans (), h)); + return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::text_ref &o) { - return hfunc (*o.ptr (), hfunc (o.trans ())); + return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); } template From 1930018f8fce23a0fe966c112c87c2a513a6097e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 25 Jun 2022 21:40:44 +0200 Subject: [PATCH 3/9] First attempt to implement DRC checks without merging - still required with certain options and not enabled to generic DRC function yet. --- src/db/db/dbAsIfFlatRegion.cc | 12 +- src/db/db/dbCompoundOperation.cc | 13 ++- src/db/db/dbDeepRegion.cc | 13 ++- src/db/db/dbRegionLocalOperations.cc | 145 ++++++++++++++++++------ src/db/db/dbRegionLocalOperations.h | 16 ++- src/db/db/gsiDeclDbCompoundOperation.cc | 2 +- 6 files changed, 157 insertions(+), 44 deletions(-) diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 47a87419e..0001342df 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -1037,7 +1037,10 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, { #if defined(USE_LOCAL_PROCESSOR) - db::RegionIterator polygons (begin_merged ()); + bool needs_merged_primary = different_polygons || options.needs_merged (); + + db::RegionIterator polygons (needs_merged_primary ? begin_merged () : begin ()); + bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); EdgeRelationFilter check (rel, d, options.metrics); check.set_include_zero (false); @@ -1059,9 +1062,12 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, if (other == subject_regionptr () || other == foreign_regionptr ()) { foreign.push_back (other == foreign_regionptr ()); others.push_back (begin_merged ()); + other_is_merged = primary_is_merged; } else { foreign.push_back (false); - if (options.whole_edges) { + if (! other->merged_semantics ()) { + other_is_merged = true; + } else if (options.whole_edges) { // NOTE: whole edges needs both inputs merged others.push_back (other->begin_merged ()); other_is_merged = true; @@ -1072,7 +1078,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, has_other = true; } - db::check_local_operation op (check, different_polygons, has_other, other_is_merged, options); + db::check_local_operation op (check, different_polygons, primary_is_merged, has_other, other_is_merged, options); std::unique_ptr output (new FlatEdgePairs ()); std::vector results; diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index 1a569a7b9..11122a2ae 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -1555,10 +1555,13 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi m_check.set_max_projection (options.max_projection); } -CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode * /*input*/, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) +CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) : CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options) { + tl_assert (input == 0); // input is a dummy parameter + m_has_other = other->has_external_inputs (); +// @@@ needs a concept to deal with merged/non-merged inputs m_is_other_merged = other->is_merged (); set_description ("check"); @@ -1585,7 +1588,9 @@ CompoundRegionCheckOperationNode::computed_dist () const void CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const { - db::check_local_operation op (m_check, m_different_polygons, m_has_other, m_is_other_merged, m_options); +// @@@ needs a concept to deal with merged/non-merged primary +bool is_merged = true; + db::check_local_operation op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); tl_assert (results.size () == 1); if (results.front ().empty ()) { @@ -1601,7 +1606,9 @@ CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache void CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const { - db::check_local_operation op (m_check, m_different_polygons, m_has_other, m_is_other_merged, m_options); +// @@@ needs a concept to deal with merged/non-merged primary +bool is_merged = true; + db::check_local_operation op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); tl_assert (results.size () == 1); if (results.front ().empty ()) { diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index f0886c723..f38d94228 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1647,16 +1647,23 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons unsigned int other_layer = 0; bool other_is_merged = true; + bool needs_merged_primary = different_polygons || options.needs_merged (); + bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); + if (other == subject_regionptr ()) { other_layer = subject_idlayer (); + other_is_merged = primary_is_merged; } else if (other == foreign_regionptr ()) { other_layer = foreign_idlayer (); + other_is_merged = primary_is_merged; } else { other_deep = dynamic_cast (other->delegate ()); if (! other_deep) { return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, options); } - if (options.whole_edges) { + if (! other->merged_semantics ()) { + other_is_merged = true; + } else if (options.whole_edges) { // NOTE: whole edges needs both inputs merged other_layer = other_deep->merged_deep_layer ().layer (); other_is_merged = true; @@ -1666,7 +1673,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons } } - const db::DeepLayer &polygons = merged_deep_layer (); + const db::DeepLayer &polygons = needs_merged_primary ? merged_deep_layer () : deep_layer (); EdgeRelationFilter check (rel, d, options.metrics); check.set_include_zero (false); @@ -1677,7 +1684,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons std::unique_ptr res (new db::DeepEdgePairs (polygons.derived ())); - db::CheckLocalOperation op (check, different_polygons, other_deep != 0, other_is_merged, options); + db::CheckLocalOperation op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options); db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index c2a399411..cd4f9ea1c 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -122,8 +122,8 @@ static bool shields_interaction (const db::EdgePair &ep, const P &poly) } template -check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options) - : m_check (check), m_different_polygons (different_polygons), m_has_other (has_other), m_other_is_merged (other_is_merged), m_options (options) +check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options) + : m_check (check), m_different_polygons (different_polygons), m_is_merged (is_merged), m_has_other (has_other), m_other_is_merged (other_is_merged), m_options (options) { // .. nothing yet .. } @@ -210,6 +210,10 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape std::list heap; std::unordered_set polygons; + std::unordered_set spolygons; + + db::EdgeProcessor ep; + ep.set_base_verbosity (50); std::set ids; for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { @@ -245,14 +249,50 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape if (m_has_other) { size_t n = 0; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const TS &subject = interactions.subject_shape (i->first); - if (! take_all) { - poly_check.enter (subject, n, common_box); - } else { - poly_check.enter (subject, n); + + if (m_is_merged) { + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const TS &subject = interactions.subject_shape (i->first); + if (! take_all) { + poly_check.enter (subject, n, common_box); + } else { + poly_check.enter (subject, n); + } + n += 2; } - n += 2; + + } else { + + // merge needed for the subject shapes + + ep.clear (); + size_t nn = 0; + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const TS &is = interactions.subject_shape (i->first); + for (typename TS::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + spolygons.clear (); + + db::polygon_ref_generator ps (layout, spolygons); + db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (pg, op); + + for (typename std::unordered_set::const_iterator o = spolygons.begin (); o != spolygons.end (); ++o) { + if (! take_all) { + poly_check.enter (*o, n, common_box); + } else { + poly_check.enter (*o, n); + } + n += 2; + } + } // merge the intruders to remove inner edges @@ -266,18 +306,16 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape // NOTE: this local merge is not necessarily giving the same results than a global merge before running // the processor. Reason: the search range is limited, hence not all necessary components may have been // captured. - db::EdgeProcessor ep; - ep.set_base_verbosity (50); ep.clear (); - size_t i = 0; + size_t nn = 0; for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { const TI &is = interactions.intruder_shape (*id).second; for (typename TI::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, i); + ep.insert (*e, nn); } - ++i; + ++nn; } polygons.clear (); @@ -317,30 +355,71 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape size_t n = 0; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - // we can't directly insert because TS may be != TI - const TS &ts = interactions.subject_shape (i->first); - insert_into_hash (polygons, ts); - if (! take_all) { - poly_check.enter (ts, n, common_box); - } else { - poly_check.enter (ts, n); - } - n += 2; - } + if (m_is_merged) { - n = 1; - - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { - const TI &ti = interactions.intruder_shape (*id).second; - if (polygons.find (ti) == polygons.end ()) { + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + // we can't directly insert because TS may be != TI + const TS &ts = interactions.subject_shape (i->first); + insert_into_hash (polygons, ts); if (! take_all) { - poly_check.enter (ti, n, common_box); + poly_check.enter (ts, n, common_box); } else { - poly_check.enter (ti, n); + poly_check.enter (ts, n); } - n += 2; + ++n; } + + for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + if (polygons.find (ti) == polygons.end ()) { + if (! take_all) { + poly_check.enter (ti, n, common_box); + } else { + poly_check.enter (ti, n); + } + ++n; + } + } + + } else { + + // merge needed for the subject shapes + + ep.clear (); + size_t nn = 0; + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + for (typename TS::polygon_edge_iterator e = ts.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + for (typename TI::polygon_edge_iterator e = ti.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + spolygons.clear (); + + db::polygon_ref_generator ps (layout, spolygons); + db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (pg, op); + + for (typename std::unordered_set::const_iterator o = spolygons.begin (); o != spolygons.end (); ++o) { + if (! take_all) { + poly_check.enter (*o, n, common_box); + } else { + poly_check.enter (*o, n); + } + ++n; + } + } } diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index d5734850f..6d81c2b0d 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -197,6 +197,19 @@ struct DB_PUBLIC RegionCheckOptions * @brief Specifies whether to produce negative output */ bool negative; + + /** + * @brief Gets a value indicating whether merged primary input is required + */ + bool needs_merged () const + { + return negative + || rect_filter != NoRectFilter + || opposite_filter != NoOppositeFilter + || max_projection != std::numeric_limits::max () + || min_projection != 0 + || whole_edges; + } }; template @@ -204,7 +217,7 @@ class check_local_operation : public local_operation { public: - check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options); + check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options); virtual db::Coord dist () const; virtual OnEmptyIntruderHint on_empty_intruder_hint () const; @@ -216,6 +229,7 @@ public: private: EdgeRelationFilter m_check; bool m_different_polygons; + bool m_is_merged; bool m_has_other; bool m_other_is_merged; db::RegionCheckOptions m_options; diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index 8d6ed008e..cefa9a1b8 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -390,7 +390,7 @@ static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges (db::Compo static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) { check_non_null (other, "other"); - return new db::CompoundRegionCheckOperationNode (new_primary (), other, rel, different_polygons, d, + return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d, db::RegionCheckOptions (whole_edges, metrics, ignore_angle.is_nil () ? 90 : ignore_angle.to_double (), From 43b63923a709ddf1fa43b40127381cf627846ab4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 01:00:33 +0200 Subject: [PATCH 4/9] WIP --- src/db/db/dbAsIfFlatRegion.cc | 1 + src/db/db/dbHash.h | 43 ++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 0001342df..e0bb9dd4e 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -1038,6 +1038,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, #if defined(USE_LOCAL_PROCESSOR) bool needs_merged_primary = different_polygons || options.needs_merged (); +needs_merged_primary = true; // @@@ db::RegionIterator polygons (needs_merged_primary ? begin_merged () : begin ()); bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); diff --git a/src/db/db/dbHash.h b/src/db/db/dbHash.h index 59d9b882b..9ed98ae0b 100644 --- a/src/db/db/dbHash.h +++ b/src/db/db/dbHash.h @@ -252,8 +252,15 @@ namespace std h = hfunc_coord (o.bgn_ext (), h); h = hfunc_coord (o.end_ext (), h); h = hfunc_coord (o.width (), h); + // NOTE: using too many points for the hash function just slows down the code. + unsigned int n = 20; for (typename db::path::iterator p = o.begin (); p != o.end (); ++p) { - h = hfunc (*p, h); + if (--n == 0) { + h = hfunc (o.points (), h); + break; + } else { + h = hfunc (*p, h); + } } return h; } @@ -280,8 +287,15 @@ namespace std template size_t hfunc (const db::polygon_contour &o, size_t h) { + // NOTE: using too many points for the hash function just slows down the code. + unsigned int n = 20; for (typename db::polygon_contour::simple_iterator i = o.begin (); i != o.end (); ++i) { - h = hfunc (*i, h); + if (--n == 0) { + h = hfunc (o.size (), h); + break; + } else { + h = hfunc (*i, h); + } } return h; } @@ -309,8 +323,15 @@ namespace std size_t hfunc (const db::polygon &o, size_t h) { h = hfunc (o.hull (), h); + // NOTE: using too many points for the hash function just slows down the code. + unsigned int n = 20; for (size_t i = 0; i < o.holes (); ++i) { - h = hfunc (o.hole (int (i)), h); + if (--n == 0) { + h = hfunc (o.holes (), h); + break; + } else { + h = hfunc (o.hole (int (i)), h); + } } return h; } @@ -514,13 +535,13 @@ namespace std template size_t hfunc (const db::shape_ref &o, size_t h) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); + return hfunc (*o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::shape_ref &o) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); + return hfunc (*o.ptr (), hfunc (o.trans ())); } template @@ -539,13 +560,13 @@ namespace std template size_t hfunc (const db::polygon_ref &o, size_t h) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); + return hfunc (*o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::polygon_ref &o) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); + return hfunc (*o.ptr (), hfunc (o.trans ())); } template @@ -564,13 +585,13 @@ namespace std template size_t hfunc (const db::path_ref &o, size_t h) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); + return hfunc (*o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::path_ref &o) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); + return hfunc (*o.ptr (), hfunc (o.trans ())); } template @@ -589,13 +610,13 @@ namespace std template size_t hfunc (const db::text_ref &o, size_t h) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans (), h)); + return hfunc (*o.ptr (), hfunc (o.trans (), h)); } template size_t hfunc (const db::text_ref &o) { - return hfunc ((size_t) o.ptr (), hfunc (o.trans ())); + return hfunc (*o.ptr (), hfunc (o.trans ())); } template From 91c85172e3124aa4c28f0d18b900fcd28df7fa80 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 01:33:49 +0200 Subject: [PATCH 5/9] WIP --- src/db/db/dbDeepRegion.cc | 1 + src/db/db/dbHash.h | 9 ++++++--- src/db/db/dbHierProcessor.cc | 11 ++++++----- src/db/db/dbRegionLocalOperations.cc | 4 ++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index f38d94228..b76dc34ef 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1648,6 +1648,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons bool other_is_merged = true; bool needs_merged_primary = different_polygons || options.needs_merged (); +needs_merged_primary = true; // @@@ bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); if (other == subject_regionptr ()) { diff --git a/src/db/db/dbHash.h b/src/db/db/dbHash.h index 9ed98ae0b..19913d2c0 100644 --- a/src/db/db/dbHash.h +++ b/src/db/db/dbHash.h @@ -253,7 +253,8 @@ namespace std h = hfunc_coord (o.end_ext (), h); h = hfunc_coord (o.width (), h); // NOTE: using too many points for the hash function just slows down the code. - unsigned int n = 20; + // @@@ unsigned int n = 20; + unsigned int n = std::numeric_limits::max (); // @@@ for (typename db::path::iterator p = o.begin (); p != o.end (); ++p) { if (--n == 0) { h = hfunc (o.points (), h); @@ -288,7 +289,8 @@ namespace std size_t hfunc (const db::polygon_contour &o, size_t h) { // NOTE: using too many points for the hash function just slows down the code. - unsigned int n = 20; + // @@@ unsigned int n = 20; + unsigned int n = std::numeric_limits::max (); // @@@ for (typename db::polygon_contour::simple_iterator i = o.begin (); i != o.end (); ++i) { if (--n == 0) { h = hfunc (o.size (), h); @@ -324,7 +326,8 @@ namespace std { h = hfunc (o.hull (), h); // NOTE: using too many points for the hash function just slows down the code. - unsigned int n = 20; + // @@@ unsigned int n = 20; + unsigned int n = std::numeric_limits::max (); // @@@ for (size_t i = 0; i < o.holes (); ++i) { if (--n == 0) { h = hfunc (o.holes (), h); diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index fc96f6cd9..1afbff8ca 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -342,11 +342,11 @@ template local_processor_cell_context & local_processor_cell_context::operator= (const local_processor_cell_context &other) { - if (this != &other) { - m_propagated = other.m_propagated; - m_drops = other.m_drops; - } - return *this; + if (this != &other) { + m_propagated = other.m_propagated; + m_drops = other.m_drops; + } + return *this; } template @@ -1221,6 +1221,7 @@ private: db::box_convert inst_bc (*mp_subject_layout, m_subject_layer); db::Box rbox = db::box_convert () (ref); +// @@@ make member of receiver? db::shape_reference_translator_with_trans rt (mp_subject_layout); for (db::CellInstArray::iterator n = inst->begin_touching (safe_box_enlarged (rbox, dist - 1, dist - 1), inst_bc); ! n.at_end (); ++n) { diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index cd4f9ea1c..4be8ca7a1 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -250,7 +250,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape size_t n = 0; - if (m_is_merged) { + if (m_is_merged || (interactions.size () == 1 && interactions.subject_shape (interactions.begin ()->first).is_box ())) { for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { const TS &subject = interactions.subject_shape (i->first); @@ -355,7 +355,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape size_t n = 0; - if (m_is_merged) { + if (m_is_merged || (interactions.size () == 1 && ids.empty () && interactions.subject_shape (interactions.begin ()->first).is_box ())) { for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { // we can't directly insert because TS may be != TI From 77b42980b6e9b6db3e56a7d2aaf0aa216ef89db6 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 01:50:45 +0200 Subject: [PATCH 6/9] WIP --- src/db/db/dbHierProcessor.cc | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 1afbff8ca..044c454c2 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -204,7 +204,7 @@ public: Ref operator() (const Ref &ref) const { - typename std::unordered_map >::const_iterator m = m_cache.find (ref.ptr ()); + auto m = m_cache.find (std::make_pair (ref.ptr (), m_bare_trans)); if (m != m_cache.end ()) { return Ref (m->second.first, ref_trans_type (m_trans * Trans (ref.trans ())) * m->second.second); @@ -221,7 +221,7 @@ public: ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh); } - m_cache[ref.ptr ()] = std::make_pair (ptr, red_trans); + m_cache[std::make_pair (ref.ptr (), m_bare_trans)] = std::make_pair (ptr, red_trans); return Ref (ptr, ref_trans_type (m_trans * Trans (ref.trans ())) * red_trans); @@ -233,7 +233,7 @@ private: Trans m_trans; ref_trans_type m_ref_trans; Trans m_bare_trans; - mutable std::unordered_map > m_cache; + mutable std::unordered_map, std::pair > m_cache; }; template @@ -1198,7 +1198,7 @@ public: typedef std::unordered_map, interactions_value_type> interactions_type; interaction_registration_inst2shape (db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, interactions_type *result) - : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result) + : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result), m_rt (subject_layout) { // nothing yet .. } @@ -1213,6 +1213,7 @@ private: unsigned int m_subject_layer; db::Coord m_dist; interactions_type *mp_result; + db::shape_reference_translator_with_trans m_rt; void collect_instance_shape_interactions (const db::CellInstArray *inst, unsigned int layer, const TI &ref, db::Coord dist) @@ -1221,9 +1222,6 @@ private: db::box_convert inst_bc (*mp_subject_layout, m_subject_layer); db::Box rbox = db::box_convert () (ref); -// @@@ make member of receiver? - db::shape_reference_translator_with_trans rt (mp_subject_layout); - for (db::CellInstArray::iterator n = inst->begin_touching (safe_box_enlarged (rbox, dist - 1, dist - 1), inst_bc); ! n.at_end (); ++n) { db::ICplxTrans tn = inst->complex_trans (*n); @@ -1232,7 +1230,7 @@ private: if (! cbox.empty ()) { db::ICplxTrans tni = tn.inverted (); - rt.set_trans (tni); + m_rt.set_trans (tni); std::set *shapes = 0; @@ -1244,7 +1242,7 @@ private: if (! shapes) { shapes = & (*mp_result) [std::make_pair (cell.cell_index (), tn)].second [layer]; } - shapes->insert (rt (ref)); + shapes->insert (m_rt (ref)); } } From bed9ac94b0642fbffef42df55e7c43716c3baceb Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 18:03:15 +0200 Subject: [PATCH 7/9] WIP --- src/db/db/dbDeepRegion.cc | 1 - src/db/db/dbRegionLocalOperations.cc | 131 +++++++++++++++++++-------- 2 files changed, 91 insertions(+), 41 deletions(-) diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index b76dc34ef..f38d94228 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1648,7 +1648,6 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons bool other_is_merged = true; bool needs_merged_primary = different_polygons || options.needs_merged (); -needs_merged_primary = true; // @@@ bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); if (other == subject_regionptr ()) { diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 4be8ca7a1..fcd0e98da 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -208,16 +208,16 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape edge2edge_check_negative_or_positive > edge_check (m_check, result, intra_polygon_result, m_options.negative, m_different_polygons, m_has_other, m_options.shielded, symmetric_edge_pairs); poly2poly_check poly_check (edge_check); - std::list heap; std::unordered_set polygons; std::unordered_set spolygons; + std::unordered_set subjects; db::EdgeProcessor ep; ep.set_base_verbosity (50); std::set ids; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + for (auto j = i->second.begin (); j != i->second.end (); ++j) { ids.insert (*j); } } @@ -230,13 +230,13 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape db::Vector e (edge_check.distance (), edge_check.distance ()); db::Box subject_box; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { subject_box += db::box_convert () (interactions.subject_shape (i->first)); } if (edge_check.requires_different_layers ()) { db::Box intruder_box; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + for (auto id = ids.begin (); id != ids.end (); ++id) { intruder_box += db::box_convert () (interactions.intruder_shape (*id).second); } common_box = subject_box.enlarged (e) & intruder_box.enlarged (e); @@ -252,7 +252,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape if (m_is_merged || (interactions.size () == 1 && interactions.subject_shape (interactions.begin ()->first).is_box ())) { - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { const TS &subject = interactions.subject_shape (i->first); if (! take_all) { poly_check.enter (subject, n, common_box); @@ -269,7 +269,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.clear (); size_t nn = 0; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { const TS &is = interactions.subject_shape (i->first); for (typename TS::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { ep.insert (*e, nn); @@ -284,7 +284,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape db::SimpleMerge op (1 /*wc>0*/); ep.process (pg, op); - for (typename std::unordered_set::const_iterator o = spolygons.begin (); o != spolygons.end (); ++o) { + for (auto o = spolygons.begin (); o != spolygons.end (); ++o) { if (! take_all) { poly_check.enter (*o, n, common_box); } else { @@ -310,9 +310,9 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.clear (); size_t nn = 0; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + for (auto id = ids.begin (); id != ids.end (); ++id) { const TI &is = interactions.intruder_shape (*id).second; - for (typename TI::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { + for (auto e = is.begin_edge (); ! e.at_end (); ++e) { ep.insert (*e, nn); } ++nn; @@ -326,7 +326,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.process (pg, op); n = 1; - for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { + for (auto o = polygons.begin (); o != polygons.end (); ++o) { if (! take_all) { poly_check.enter (*o, n, common_box); } else { @@ -338,7 +338,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape } else { n = 1; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + for (auto id = ids.begin (); id != ids.end (); ++id) { if (! take_all) { poly_check.enter (interactions.intruder_shape (*id).second, n, common_box); } else { @@ -353,32 +353,22 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield + // subject handling + size_t n = 0; - if (m_is_merged || (interactions.size () == 1 && ids.empty () && interactions.subject_shape (interactions.begin ()->first).is_box ())) { + if (m_is_merged || (interactions.size () == 1 && interactions.subject_shape (interactions.begin ()->first).is_box ())) { - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { // we can't directly insert because TS may be != TI const TS &ts = interactions.subject_shape (i->first); - insert_into_hash (polygons, ts); + insert_into_hash (subjects, ts); if (! take_all) { poly_check.enter (ts, n, common_box); } else { poly_check.enter (ts, n); } - ++n; - } - - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { - const TI &ti = interactions.intruder_shape (*id).second; - if (polygons.find (ti) == polygons.end ()) { - if (! take_all) { - poly_check.enter (ti, n, common_box); - } else { - poly_check.enter (ti, n); - } - ++n; - } + n += 2; } } else { @@ -388,17 +378,9 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.clear (); size_t nn = 0; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { const TS &ts = interactions.subject_shape (i->first); - for (typename TS::polygon_edge_iterator e = ts.begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, nn); - } - ++nn; - } - - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { - const TI &ti = interactions.intruder_shape (*id).second; - for (typename TI::polygon_edge_iterator e = ti.begin_edge (); ! e.at_end (); ++e) { + for (auto e = ts.begin_edge (); ! e.at_end (); ++e) { ep.insert (*e, nn); } ++nn; @@ -411,13 +393,82 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape db::SimpleMerge op (1 /*wc>0*/); ep.process (pg, op); - for (typename std::unordered_set::const_iterator o = spolygons.begin (); o != spolygons.end (); ++o) { + for (auto o = spolygons.begin (); o != spolygons.end (); ++o) { + insert_into_hash (subjects, *o); if (! take_all) { poly_check.enter (*o, n, common_box); } else { poly_check.enter (*o, n); } - ++n; + n += 2; + } + + } + + // intruder handling + + n = 1; + + if (ids.empty ()) { + + // nothing to supply + + } else if (! m_is_merged) { + + // merge needed for intruders - we do a boolean NOT with the subject shape to + // avoid shielding + + ep.clear (); + size_t nn = 0; + + for (auto id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + if (subjects.find (ti) == subjects.end ()) { + for (auto e = ti.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + nn += 2; + } + } + + if (nn > 0) { + + nn = 1; + for (auto i = subjects.begin (); i != subjects.end (); ++i) { + for (auto e = i->begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + nn += 2; + } + + polygons.clear (); + + db::polygon_ref_generator ps (layout, polygons); + db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); + db::BooleanOp op (db::BooleanOp::ANotB); + ep.process (pg, op); + + for (auto o = polygons.begin (); o != polygons.end (); ++o) { + if (! take_all) { + poly_check.enter (*o, n, common_box); + } else { + poly_check.enter (*o, n); + } + } + + } + + } else { + + for (auto id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + if (subjects.find (ti) == subjects.end ()) { + if (! take_all) { + poly_check.enter (ti, n, common_box); + } else { + poly_check.enter (ti, n); + } + } } } From 47c9243c044f421a6750a2f72e7693aa1e8ccc63 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 21:16:34 +0200 Subject: [PATCH 8/9] WIP --- src/db/db/dbPolygon.h | 1 + src/db/db/dbRegionCheckUtils.cc | 18 ++++ src/db/db/dbRegionCheckUtils.h | 3 + src/db/db/dbRegionLocalOperations.cc | 153 ++++++++++++++++----------- 4 files changed, 113 insertions(+), 62 deletions(-) diff --git a/src/db/db/dbPolygon.h b/src/db/db/dbPolygon.h index 1b59dfc5f..d00a099c7 100644 --- a/src/db/db/dbPolygon.h +++ b/src/db/db/dbPolygon.h @@ -3075,6 +3075,7 @@ public: typedef typename Poly::coord_type coord_type; typedef typename Poly::point_type point_type; typedef typename Poly::box_type box_type; + typedef typename Poly::edge_type edge_type; typedef Trans trans_type; typedef Poly polygon_type; typedef db::polygon_edge_iterator polygon_edge_iterator; diff --git a/src/db/db/dbRegionCheckUtils.cc b/src/db/db/dbRegionCheckUtils.cc index c8183fa46..e09fa60ee 100644 --- a/src/db/db/dbRegionCheckUtils.cc +++ b/src/db/db/dbRegionCheckUtils.cc @@ -468,6 +468,14 @@ poly2poly_check::enter (const PolygonType &o, size_t p) } } +template +void +poly2poly_check::enter (const poly2poly_check::edge_type &e, size_t p) +{ + m_edge_heap.push_back (e); + m_scanner.insert (& m_edge_heap.back (), p); +} + // TODO: move to generic header static bool interact (const db::Box &box, const db::Edge &e) { @@ -496,6 +504,16 @@ poly2poly_check::enter (const PolygonType &o, size_t p, const poly2 } } +template +void +poly2poly_check::enter (const poly2poly_check::edge_type &e, size_t p, const poly2poly_check::box_type &box) +{ + if (! box.empty () && interact (box, e)) { + m_edge_heap.push_back (e); + m_scanner.insert (& m_edge_heap.back (), p); + } +} + template void poly2poly_check::process () diff --git a/src/db/db/dbRegionCheckUtils.h b/src/db/db/dbRegionCheckUtils.h index 6c19ed0c3..41ad724d6 100644 --- a/src/db/db/dbRegionCheckUtils.h +++ b/src/db/db/dbRegionCheckUtils.h @@ -310,6 +310,7 @@ class DB_PUBLIC poly2poly_check { public: typedef typename PolygonType::box_type box_type; + typedef typename PolygonType::edge_type edge_type; poly2poly_check (Edge2EdgeCheckBase &output); poly2poly_check (); @@ -321,6 +322,8 @@ public: void connect (Edge2EdgeCheckBase &output); void enter (const PolygonType &o, size_t p); void enter (const PolygonType &o, size_t p, const box_type &search_box); + void enter (const edge_type &o, size_t p); + void enter (const edge_type &o, size_t p, const box_type &search_box); void process (); private: diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index fcd0e98da..d6aa19b9e 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -210,7 +210,6 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape std::unordered_set polygons; std::unordered_set spolygons; - std::unordered_set subjects; db::EdgeProcessor ep; ep.set_base_verbosity (50); @@ -318,6 +317,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ++nn; } +// @@@ Use edges directly polygons.clear (); db::polygon_ref_generator ps (layout, polygons); @@ -351,13 +351,14 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape } else { - // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield + if (m_is_merged || (interactions.size () == 1 && ids.empty () && interactions.subject_shape (interactions.begin ()->first).is_box ())) { - // subject handling + // no merge required - size_t n = 0; + // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield - if (m_is_merged || (interactions.size () == 1 && interactions.subject_shape (interactions.begin ()->first).is_box ())) { + size_t n = 0; + std::unordered_set subjects; for (auto i = interactions.begin (); i != interactions.end (); ++i) { // we can't directly insert because TS may be != TI @@ -371,9 +372,24 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape n += 2; } - } else { + n = 1; - // merge needed for the subject shapes + for (auto id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + if (subjects.find (ti) == subjects.end ()) { + if (! take_all) { + poly_check.enter (ti, n, common_box); + } else { + poly_check.enter (ti, n); + } + } + } + + } else if (ids.empty ()) { + + // merge needed for the subject shapes - no intruders present so this is the simple case + + size_t n = 0; ep.clear (); size_t nn = 0; @@ -386,6 +402,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ++nn; } +// @@@ Use edges directly spolygons.clear (); db::polygon_ref_generator ps (layout, spolygons); @@ -394,7 +411,6 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.process (pg, op); for (auto o = spolygons.begin (); o != spolygons.end (); ++o) { - insert_into_hash (subjects, *o); if (! take_all) { poly_check.enter (*o, n, common_box); } else { @@ -403,72 +419,85 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape n += 2; } - } + } else { - // intruder handling - - n = 1; - - if (ids.empty ()) { - - // nothing to supply - - } else if (! m_is_merged) { - - // merge needed for intruders - we do a boolean NOT with the subject shape to - // avoid shielding + // merge needed for the subject and intruder shapes - we merge both and then + // separate edges into those from the subject and those from intruder shapes. ep.clear (); size_t nn = 0; - for (auto id = ids.begin (); id != ids.end (); ++id) { - const TI &ti = interactions.intruder_shape (*id).second; - if (subjects.find (ti) == subjects.end ()) { - for (auto e = ti.begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, nn); - } - nn += 2; + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + for (auto e = ts.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); } + ++nn; } - if (nn > 0) { - - nn = 1; - for (auto i = subjects.begin (); i != subjects.end (); ++i) { - for (auto e = i->begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, nn); - } - nn += 2; - } - - polygons.clear (); - - db::polygon_ref_generator ps (layout, polygons); - db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); - db::BooleanOp op (db::BooleanOp::ANotB); - ep.process (pg, op); - - for (auto o = polygons.begin (); o != polygons.end (); ++o) { - if (! take_all) { - poly_check.enter (*o, n, common_box); - } else { - poly_check.enter (*o, n); - } - } - - } - - } else { - for (auto id = ids.begin (); id != ids.end (); ++id) { const TI &ti = interactions.intruder_shape (*id).second; - if (subjects.find (ti) == subjects.end ()) { - if (! take_all) { - poly_check.enter (ti, n, common_box); - } else { - poly_check.enter (ti, n); + for (auto e = ti.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + std::vector edges; + + db::EdgeContainer ee (edges); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (ee, op); + ep.clear (); + + std::vector subject_edges; + + size_t sz = 0; + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + sz += ts.vertices (); + } + + subject_edges.reserve (sz); + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + for (auto e = ts.begin_edge (); ! e.at_end (); ++e) { + subject_edges.push_back (*e); + } + } + + for (size_t n = 0; n <= 1; ++n) { + + std::set partial_edges; + + EdgeBooleanClusterCollector > cluster_collector (&partial_edges, n == 0 ? db::EdgeAnd : db::EdgeNot); + + db::box_scanner scanner; + scanner.reserve (edges.size () + subject_edges.size ()); + + for (auto i = edges.begin (); i != edges.end (); ++i) { + if (! i->is_degenerate ()) { + scanner.insert (i.operator-> (), 0); } } + + for (auto i = subject_edges.begin (); i != subject_edges.end (); ++i) { + if (! i->is_degenerate ()) { + scanner.insert (i.operator-> (), 1); + } + } + + scanner.process (cluster_collector, 1, db::box_convert ()); + + for (auto e = partial_edges.begin (); e != partial_edges.end (); ++e) { + if (! take_all) { + poly_check.enter (*e, n, common_box); + } else { + poly_check.enter (*e, n); + } + } + } } From 0edeac2efa00ed733e5e0f682d8ca9fdeec1c613 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 23:06:29 +0200 Subject: [PATCH 9/9] WIP --- src/db/db/dbHash.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/db/db/dbHash.h b/src/db/db/dbHash.h index 19913d2c0..9ed98ae0b 100644 --- a/src/db/db/dbHash.h +++ b/src/db/db/dbHash.h @@ -253,8 +253,7 @@ namespace std h = hfunc_coord (o.end_ext (), h); h = hfunc_coord (o.width (), h); // NOTE: using too many points for the hash function just slows down the code. - // @@@ unsigned int n = 20; - unsigned int n = std::numeric_limits::max (); // @@@ + unsigned int n = 20; for (typename db::path::iterator p = o.begin (); p != o.end (); ++p) { if (--n == 0) { h = hfunc (o.points (), h); @@ -289,8 +288,7 @@ namespace std size_t hfunc (const db::polygon_contour &o, size_t h) { // NOTE: using too many points for the hash function just slows down the code. - // @@@ unsigned int n = 20; - unsigned int n = std::numeric_limits::max (); // @@@ + unsigned int n = 20; for (typename db::polygon_contour::simple_iterator i = o.begin (); i != o.end (); ++i) { if (--n == 0) { h = hfunc (o.size (), h); @@ -326,8 +324,7 @@ namespace std { h = hfunc (o.hull (), h); // NOTE: using too many points for the hash function just slows down the code. - // @@@ unsigned int n = 20; - unsigned int n = std::numeric_limits::max (); // @@@ + unsigned int n = 20; for (size_t i = 0; i < o.holes (); ++i) { if (--n == 0) { h = hfunc (o.holes (), h);