From 5dc833970b8d2bed1ca9e765f1667540ba616922 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 16 Feb 2019 22:34:36 +0100 Subject: [PATCH] Hierarchical implementation DRC functions (measurements) --- src/db/db/dbDeepRegion.cc | 99 ++++++++++++------- src/db/db/dbEdgePairs.h | 14 ++- src/db/db/dbHierProcessor.cc | 10 +- src/db/unit_tests/dbDeepRegionTests.cc | 86 ++++++++++++++++ .../gds2/db_plugin/dbGDS2WriterBase.cc | 11 ++- .../gds2/db_plugin/dbGDS2WriterBase.h | 5 + 6 files changed, 181 insertions(+), 44 deletions(-) diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 457252481..3fe83e3c6 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -716,14 +716,14 @@ DeepRegion::to_string (size_t nmax) const EdgePairs DeepRegion::grid_check (db::Coord gx, db::Coord gy) const { - // NOTE: snap be optimized by forming grid variants etc. + // TODO: snap be optimized by forming grid variants etc. return db::AsIfFlatRegion::grid_check (gx, gy); } EdgePairs DeepRegion::angle_check (double min, double max, bool inverse) const { - // NOTE: snap be optimized by forming rotation variants etc. + // TODO: snap be optimized by forming rotation variants etc. return db::AsIfFlatRegion::angle_check (min, max, inverse); } @@ -1241,41 +1241,63 @@ class CheckLocalOperation : public local_operation { public: - CheckLocalOperation (const EdgeRelationFilter &check, bool different_polygons) - : m_check (check), m_different_polygons (different_polygons) + CheckLocalOperation (const EdgeRelationFilter &check, bool different_polygons, bool has_other) + : m_check (check), m_different_polygons (different_polygons), m_has_other (has_other) { // .. nothing yet .. } virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const { - edge2edge_check > edge_check (m_check, result, false, false); + edge2edge_check > edge_check (m_check, result, m_different_polygons, m_has_other); poly2poly_check > poly_check (edge_check); - std::set others; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - others.insert (interactions.intruder_shape (*j)); - } - } - - size_t n = 0; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) { - const db::PolygonRef &subject = interactions.subject_shape (i->first); - db::Polygon poly = subject.obj ().transformed (subject.trans ()); - poly_check.enter (poly, n); - n += 2; - } - - n = 1; - for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { - db::Polygon poly = o->obj ().transformed (o->trans ()); - poly_check.enter (poly, n); - n += 2; - } - + std::list heap; db::box_scanner scanner; + if (m_has_other) { + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); + } + } + + size_t n = 0; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::PolygonRef &subject = interactions.subject_shape (i->first); + heap.push_back (subject.obj ().transformed (subject.trans ())); + scanner.insert (& heap.back (), n); + n += 2; + } + + n = 1; + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + heap.push_back (o->obj ().transformed (o->trans ())); + scanner.insert (& heap.back (), n); + n += 2; + } + + } else { + + std::set polygons; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + polygons.insert (interactions.subject_shape (i->first)); + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + polygons.insert (interactions.intruder_shape (*j)); + } + } + + size_t n = 0; + for (std::set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { + heap.push_back (o->obj ().transformed (o->trans ())); + scanner.insert (& heap.back (), n); + n += 2; + } + + } + do { scanner.process (poly_check, m_check.distance (), db::box_convert ()); } while (edge_check.prepare_next_pass ()); @@ -1283,7 +1305,7 @@ public: virtual db::Coord dist () const { - // TODO: will the distance be sufficient? Or should be take somewhat more? + // TODO: will the distance be sufficient? Or should we take somewhat more? return m_check.distance (); } @@ -1300,6 +1322,7 @@ public: private: EdgeRelationFilter m_check; bool m_different_polygons; + bool m_has_other; }; } @@ -1307,9 +1330,12 @@ private: EdgePairs DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const { - const db::DeepRegion *other_deep = dynamic_cast (other->delegate ()); - if (! other_deep) { - return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection); + const db::DeepRegion *other_deep = 0; + if (other) { + other_deep = dynamic_cast (other->delegate ()); + if (! other_deep) { + return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection); + } } ensure_merged_polygons_valid (); @@ -1320,16 +1346,19 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons check.set_min_projection (min_projection); check.set_max_projection (max_projection); - DeepLayer dl_out (m_deep_layer.derived ()); std::auto_ptr res (new db::DeepEdgePairs (m_merged_polygons.derived ())); - db::CheckLocalOperation op (check, different_polygons); + db::CheckLocalOperation op (check, different_polygons, other_deep != 0); + + db::local_processor proc (const_cast (&m_deep_layer.layout ()), + const_cast (&m_deep_layer.initial_cell ()), + other_deep ? &other_deep->deep_layer ().layout () : const_cast (&m_deep_layer.layout ()), + other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&m_deep_layer.initial_cell ())); - db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); proc.set_base_verbosity (base_verbosity ()); proc.set_threads (m_deep_layer.store ()->threads ()); - proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ()); + proc.run (&op, m_merged_polygons.layer (), other_deep ? other_deep->deep_layer ().layer () : m_merged_polygons.layer (), res->deep_layer ().layer ()); return db::EdgePairs (res.release ()); } diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index 2cb19df22..dc48c3e61 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -274,8 +274,18 @@ public: * * Creates an edge pair set representing a single instance of that object */ - template - explicit EdgePairs (const Sh &s) + explicit EdgePairs (const db::EdgePair &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Constructor from an object + * + * Creates an edge pair set representing a single instance of that object + */ + explicit EdgePairs (const db::Shape &s) : mp_delegate (0) { insert (s); diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index b549ac921..a88743c18 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -315,10 +315,10 @@ local_processor_cell_context::propagate (const std::unordered_set; template class DB_PUBLIC local_processor_cell_context; -template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; -template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; // --------------------------------------------------------------------------------------------- // LocalProcessorCellContexts implementation @@ -1033,7 +1033,7 @@ template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; -template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; // --------------------------------------------------------------------------------------------- // LocalProcessor implementation @@ -1610,10 +1610,10 @@ local_processor::compute_local_cell (const db::local_processor_conte template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; -template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; -template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; } diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index f00fff9fe..7597be1b2 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -927,6 +927,92 @@ TEST(16_MergeWithMinWC) } } +TEST(17_SinglePolygonChecks) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0)); + unsigned int l4 = ly.get_layer (db::LayerProperties (4, 0)); + + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss); + db::Region r4 (db::RecursiveShapeIterator (ly, top_cell, l4), dss); + + { + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (4, 0)), r4); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (6, 0)), r6); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r3.width_check (260, false, db::Euclidian, 90, 0)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3.width_check (260, true, db::Projection, 90, 2000)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r6.notch_check (1300, false, db::Euclidian, 90, 0)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au17.gds"); + } +} + +TEST(18_Checks) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0)); + unsigned int l4 = ly.get_layer (db::LayerProperties (4, 0)); + + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss); + db::Region r4 (db::RecursiveShapeIterator (ly, top_cell, l4), dss); + + { + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (4, 0)), r4); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (6, 0)), r6); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r3.space_check (500, false, db::Projection, 90, 0)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3.space_check (500, true, db::Projection, 90, 300)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r3.separation_check (r4, 200, false, db::Projection, 90, 0)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r6.enclosing_check (r4, 100, true, db::Projection, 90, 0)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au18.gds"); + } +} + TEST(100_Integration) { db::Layout ly; diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.cc index 96f58c136..6f8d53f4f 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.cc @@ -296,7 +296,7 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S int layer = l->second.layer; int datatype = l->second.datatype; - db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Texts)); + db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::EdgePairs | db::ShapeIterator::Paths | db::ShapeIterator::Texts)); while (! shape.at_end ()) { progress_checkpoint (); @@ -307,6 +307,9 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S write_polygon (layer, datatype, sf, *shape, multi_xy, max_vertex_count, layout, shape->prop_id ()); } else if (shape->is_edge ()) { write_edge (layer, datatype, sf, *shape, layout, shape->prop_id ()); + } else if (shape->is_edge_pair ()) { + write_edge (layer, datatype, sf, shape->edge_pair ().first (), layout, shape->prop_id ()); + write_edge (layer, datatype, sf, shape->edge_pair ().second (), layout, shape->prop_id ()); } else if (shape->is_path ()) { if (no_zero_length_paths && (shape->path_length () - shape->path_extensions ().first - shape->path_extensions ().second) == 0) { // eliminate the zero-width path @@ -580,8 +583,12 @@ GDS2WriterBase::write_path (int layer, int datatype, double sf, const db::Shape void GDS2WriterBase::write_edge (int layer, int datatype, double sf, const db::Shape &shape, const db::Layout &layout, db::properties_id_type prop_id) { - db::Edge e (shape.edge ()); + write_edge (layer, datatype, sf, shape.edge (), layout, prop_id); +} +void +GDS2WriterBase::write_edge (int layer, int datatype, double sf, const db::Edge &e, const db::Layout &layout, db::properties_id_type prop_id) +{ write_record_size (4); write_record (sPATH); diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.h index d0c5dd6cf..ef8249b48 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.h +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.h @@ -134,6 +134,11 @@ protected: */ void write_edge (int layer, int datatype, double sf, const db::Shape &shape, const db::Layout &layout, db::properties_id_type prop_id); + /** + * @brief Writes an edge + */ + void write_edge (int layer, int datatype, double sf, const db::Edge &edge, const db::Layout &layout, db::properties_id_type prop_id); + /** * @brief Write a shape as path */