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 (),