diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 0d7823d6c..0c46d7302 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -193,7 +193,8 @@ SOURCES = \ dbEmptyTexts.cc \ dbFlatTexts.cc \ dbTextsUtils.cc \ - dbOriginalLayerTexts.cc + dbOriginalLayerTexts.cc \ + dbNetShape.cc HEADERS = \ dbArray.h \ @@ -348,7 +349,8 @@ HEADERS = \ dbEmptyTexts.h \ dbFlatTexts.h \ dbTextsUtils.h \ - dbOriginalLayerTexts.h + dbOriginalLayerTexts.h \ + dbNetShape.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 65966361e..d69bf3959 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -394,7 +394,7 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse) scanner.reserve2 (other.size ()); std::auto_ptr output (new FlatRegion (false)); - region_to_text_interaction_filter filter (output->raw_polygons (), inverse); + region_to_text_interaction_filter filter (output->raw_polygons (), inverse); AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ()); @@ -527,7 +527,7 @@ AsIfFlatRegion::pull_generic (const Texts &other) const scanner.reserve2 (other.size ()); std::auto_ptr output (new FlatTexts (false)); - region_to_text_interaction_filter filter (output->raw_texts (), false); + region_to_text_interaction_filter filter (output->raw_texts (), false); AddressablePolygonDelivery p (begin (), has_valid_merged_polygons ()); diff --git a/src/db/db/dbAsIfFlatTexts.cc b/src/db/db/dbAsIfFlatTexts.cc index 4bad031a1..a3b8a1958 100644 --- a/src/db/db/dbAsIfFlatTexts.cc +++ b/src/db/db/dbAsIfFlatTexts.cc @@ -312,13 +312,13 @@ AsIfFlatTexts::selected_interacting_generic (const Region &other, bool inverse) if (! inverse) { - text_to_region_interaction_filter filter (*output); + text_to_region_interaction_filter filter (*output); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } else { std::set interacting; - text_to_region_interaction_filter > filter (interacting); + text_to_region_interaction_filter, db::Text> filter (interacting); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); for (TextsIterator o (begin ()); ! o.at_end (); ++o) { @@ -356,7 +356,7 @@ AsIfFlatTexts::pull_generic (const Region &other) const std::auto_ptr output (new FlatRegion (true)); - text_to_region_interaction_filter filter (*output); + text_to_region_interaction_filter filter (*output); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); return output.release (); diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index d8371e563..5ed7bfb46 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -417,7 +417,7 @@ DeepEdges::ensure_merged_edges_valid () const db::Connectivity conn; conn.connect (m_deep_layer); hc.set_base_verbosity (base_verbosity() + 10); - hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Edges, conn); + hc.build (layout, m_deep_layer.initial_cell (), conn); // collect the clusters and merge them into big polygons // NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is @@ -1077,7 +1077,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t db::Connectivity conn (db::Connectivity::EdgesConnectByPoints); conn.connect (edges); hc.set_base_verbosity (base_verbosity () + 10); - hc.build (layout, edges.initial_cell (), db::ShapeIterator::Edges, conn); + hc.build (layout, edges.initial_cell (), conn); // TODO: iterate only over the called cells? for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 42510cb7d..dac586f86 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -455,7 +455,7 @@ DeepRegion::ensure_merged_polygons_valid () const db::Connectivity conn; conn.connect (m_deep_layer); hc.set_base_verbosity (base_verbosity () + 10); - hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn); + hc.build (layout, m_deep_layer.initial_cell (), conn); // collect the clusters and merge them into big polygons // NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is @@ -1238,7 +1238,7 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const db::Connectivity conn; conn.connect (m_deep_layer); hc.set_base_verbosity (base_verbosity () + 10); - hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn); + hc.build (layout, m_deep_layer.initial_cell (), conn); // collect the clusters and merge them into big polygons // NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is @@ -1899,25 +1899,25 @@ public: struct TextResultInserter { - typedef db::Text value_type; + typedef db::TextRef value_type; - TextResultInserter (std::unordered_set &result) + TextResultInserter (std::unordered_set &result) : mp_result (&result) { // .. nothing yet .. } - void insert (const db::Text &e) + void insert (const db::TextRef &e) { (*mp_result).insert (e); } private: - std::unordered_set *mp_result; + std::unordered_set *mp_result; }; class PullWithTextLocalOperation - : public local_operation + : public local_operation { public: PullWithTextLocalOperation () @@ -1931,15 +1931,15 @@ public: return 1; } - virtual void compute_local (db::Layout *, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + virtual void compute_local (db::Layout *, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const { - db::box_scanner2 scanner; + db::box_scanner2 scanner; TextResultInserter inserter (result); - region_to_text_interaction_filter filter (inserter, false); + region_to_text_interaction_filter filter (inserter, false); - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { scanner.insert2 (& interactions.intruder_shape (*j), 0); } } @@ -1954,7 +1954,7 @@ public: } - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } virtual on_empty_intruder_mode on_empty_intruder_hint () const @@ -1969,7 +1969,7 @@ public: }; class InteractingWithTextLocalOperation - : public local_operation + : public local_operation { public: InteractingWithTextLocalOperation (bool inverse) @@ -1984,12 +1984,12 @@ public: return 1; } - virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const { - db::box_scanner2 scanner; + db::box_scanner2 scanner; ResultInserter inserter (layout, result); - region_to_text_interaction_filter filter (inserter, m_inverse); + region_to_text_interaction_filter filter (inserter, m_inverse); for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { @@ -2010,7 +2010,7 @@ public: } - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); if (m_inverse) { filter.fill_output (); } @@ -2199,7 +2199,7 @@ DeepRegion::pull_generic (const Texts &other) const db::PullWithTextLocalOperation op; - db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ()); + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ()); proc.set_base_verbosity (base_verbosity ()); proc.set_threads (polygons.store ()->threads ()); proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ()); @@ -2229,7 +2229,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse) cons db::InteractingWithTextLocalOperation op (inverse); - db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); proc.set_base_verbosity (base_verbosity ()); proc.set_threads (polygons.store ()->threads ()); if (split_after) { diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index b678b302f..c8f249a76 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -474,7 +474,7 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::IC db::Shapes *shapes = &initial_cell ().shapes (layer); db::Box world = db::Box::world (); - db::TextBuildingHierarchyBuilderShapeReceiver tb; + db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ()); std::pair ii = texts.begin_iter (); db::ICplxTrans ttop = trans * ii.second; @@ -849,7 +849,10 @@ DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterat DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans) { - db::TextBuildingHierarchyBuilderShapeReceiver refs; + unsigned int layout_index = layout_for_iter (si, trans); + db::Layout &layout = m_layouts[layout_index]->layout; + + db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout); return create_custom_layer (si, &refs, trans); } diff --git a/src/db/db/dbDeepTexts.cc b/src/db/db/dbDeepTexts.cc index 73739984f..5165de7f2 100644 --- a/src/db/db/dbDeepTexts.cc +++ b/src/db/db/dbDeepTexts.cc @@ -408,7 +408,7 @@ void DeepTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type int namespace { class Text2PolygonInteractingLocalOperation - : public local_operation + : public local_operation { public: Text2PolygonInteractingLocalOperation (bool inverse) @@ -423,19 +423,19 @@ public: return 1; } - virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const { - db::box_scanner2 scanner; + db::box_scanner2 scanner; 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) { + 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)); } } - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Text &subject = interactions.subject_shape (i->first); + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::TextRef &subject = interactions.subject_shape (i->first); scanner.insert1 (&subject, 0); } @@ -447,12 +447,12 @@ public: if (m_inverse) { - std::unordered_set interacting; - text_to_region_interaction_filter > filter (interacting); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + std::unordered_set interacting; + text_to_region_interaction_filter, db::TextRef> filter (interacting); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Text &subject = interactions.subject_shape (i->first); + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::TextRef &subject = interactions.subject_shape (i->first); if (interacting.find (subject) == interacting.end ()) { result.insert (subject); } @@ -460,8 +460,8 @@ public: } else { - text_to_region_interaction_filter > filter (result); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + text_to_region_interaction_filter, db::TextRef> filter (result); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } } @@ -505,7 +505,7 @@ private: }; class Text2PolygonPullLocalOperation - : public local_operation + : public local_operation { public: Text2PolygonPullLocalOperation () @@ -519,19 +519,19 @@ public: return 1; } - virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const { - db::box_scanner2 scanner; + db::box_scanner2 scanner; 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) { + 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)); } } - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Text &subject = interactions.subject_shape (i->first); + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::TextRef &subject = interactions.subject_shape (i->first); scanner.insert1 (&subject, 1); } @@ -542,8 +542,8 @@ public: } ResultInserter inserter (layout, result); - text_to_region_interaction_filter filter (inserter); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + text_to_region_interaction_filter filter (inserter); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } virtual on_empty_intruder_mode on_empty_intruder_hint () const @@ -576,7 +576,7 @@ DeepTexts::selected_interacting_generic (const Region &other, bool inverse) cons db::Text2PolygonInteractingLocalOperation op (inverse); - db::local_processor proc (const_cast (&texts.layout ()), const_cast (&texts.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&texts.layout ()), const_cast (&texts.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); proc.set_base_verbosity (other.base_verbosity ()); proc.set_threads (texts.store ()->threads ()); @@ -602,7 +602,7 @@ RegionDelegate *DeepTexts::pull_generic (const Region &other) const db::Text2PolygonPullLocalOperation op; - db::local_processor proc (const_cast (&texts.layout ()), const_cast (&texts.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ()); + db::local_processor proc (const_cast (&texts.layout ()), const_cast (&texts.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ()); proc.set_base_verbosity (other.base_verbosity ()); proc.set_threads (texts.store ()->threads ()); diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 08ca4d269..babb8d5fc 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -29,6 +29,7 @@ #include "dbPolygonTools.h" #include "dbBoxScanner.h" #include "dbDeepRegion.h" +#include "dbNetShape.h" #include "tlProgress.h" #include "tlLog.h" #include "tlTimer.h" @@ -43,9 +44,9 @@ namespace db // ------------------------------------------------------------------------------ -template void insert_transformed (db::Layout &layout, Container &shapes, const Shape &s, const Trans &t); +template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const Shape &s, const Trans &t); -template void insert_transformed (db::Layout &layout, Container &shapes, const db::PolygonRef &s, const Trans &t) +template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const db::PolygonRef &s, const Trans &t) { db::Polygon poly = s.obj (); poly.transform (s.trans ()); @@ -55,7 +56,32 @@ template void insert_transformed (db::Layout &lay shapes.insert (db::PolygonRef (poly, layout.shape_repository ())); } -template void insert_transformed (db::Layout & /*layout*/, Container &shapes, const db::Edge &s, const Trans &t) +template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const db::NetShape &s, const Trans &t) +{ + if (s.type () == db::NetShape::Polygon) { + + db::PolygonRef pr = s.polygon_ref (); + db::Polygon poly = pr.obj (); + poly.transform (pr.trans ()); + if (! t.is_unity ()) { + poly.transform (t); + } + shapes.insert (db::PolygonRef (poly, layout.shape_repository ())); + + } else if (s.type () == db::NetShape::Text) { + + db::TextRef tr = s.text_ref (); + db::Text text = tr.obj (); + text.transform (tr.trans ()); + if (! t.is_unity ()) { + text.transform (t); + } + shapes.insert (db::TextRef (text, layout.shape_repository ())); + + } +} + +template void insert_transformed (db::Layout & /*layout*/, db::Shapes &shapes, const db::Edge &s, const Trans &t) { shapes.insert (s.transformed (t)); } @@ -237,6 +263,20 @@ interaction_test (const db::PolygonRef &a, const db::PolygonRef &b, const db::un } } +template +static bool +interaction_test (const db::NetShape &a, const db::NetShape &b, const Trans &trans, db::Connectivity::edge_connectivity_type) +{ + return a.interacts_with_transformed (b, trans); +} + +template +static bool +interaction_test (const db::NetShape &a, const db::NetShape &b, const db::unit_trans &, db::Connectivity::edge_connectivity_type) +{ + return a.interacts_with (b); +} + template static bool interaction_test (const db::Edge &a, const db::Edge &b, const Trans &trans, db::Connectivity::edge_connectivity_type ec) @@ -272,6 +312,8 @@ bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned } // explicit instantiations +template DB_PUBLIC bool Connectivity::interacts (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::UnitTrans &trans) const; +template DB_PUBLIC bool Connectivity::interacts (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::ICplxTrans &trans) const; template DB_PUBLIC bool Connectivity::interacts (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::UnitTrans &trans) const; template DB_PUBLIC bool Connectivity::interacts (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans) const; template DB_PUBLIC bool Connectivity::interacts (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::UnitTrans &trans) const; @@ -630,8 +672,10 @@ size_t local_cluster::split (double max_area_ratio, Iter &output) const } // explicit instantiations +template class DB_PUBLIC local_cluster; template class DB_PUBLIC local_cluster; template class DB_PUBLIC local_cluster; +template DB_PUBLIC size_t local_cluster::split > > > (double, std::back_insert_iterator > > &) const; template DB_PUBLIC size_t local_cluster::split > > > (double, std::back_insert_iterator > > &) const; template DB_PUBLIC size_t local_cluster::split > > > (double, std::back_insert_iterator > > &) const; @@ -886,22 +930,112 @@ private: } }; +template +struct addressable_shape_delivery +{ + const T *operator () (const db::Shape &shape) + { + typename T::tag object_tag; + return shape.basic_ptr (object_tag); + } +}; + +template <> +struct addressable_shape_delivery +{ + const NetShape *operator () (const db::Shape &shape) + { + if (shape.type () == db::Shape::TextRef) { + m_heap.push_back (db::NetShape (shape.text_ref ())); + return &m_heap.back (); + } else if (shape.type () == db::Shape::PolygonRef) { + m_heap.push_back (db::NetShape (shape.polygon_ref ())); + return &m_heap.back (); + } else { + tl_assert (false); + } + } + +private: + std::list m_heap; +}; + +template +struct attr_accessor +{ + size_t operator() (const db::Shape &shape) const + { + return shape.prop_id (); + } +}; + +template <> +struct attr_accessor +{ + size_t operator() (const db::Shape &shape) const + { + // NOTE: the attribute is + // * odd: a StringRef pointer's value + // * even: a Property ID times 2 + if (shape.type () == db::Shape::TextRef) { + return db::text_ref_to_attr (&shape.text_ref ().obj ()); + } else { + return db::prop_id_to_attr (shape.prop_id ()); + } + } +}; + +template struct get_shape_flags { }; + +template <> +struct get_shape_flags +{ + db::ShapeIterator::flags_type operator() (bool /*with_attr*/) const + { + return db::ShapeIterator::Edges; + } +}; + +template <> +struct get_shape_flags +{ + db::ShapeIterator::flags_type operator() (bool /*with_attr*/) const + { + return db::ShapeIterator::Polygons; + } +}; + +template <> +struct get_shape_flags +{ + db::ShapeIterator::flags_type operator() (bool with_attr) const + { + if (with_attr) { + return db::ShapeIterator::flags_type (db::ShapeIterator::Polygons | db::ShapeIterator::Texts); + } else { + return db::ShapeIterator::flags_type (db::ShapeIterator::Polygons); + } + } +}; + } template void -local_clusters::build_clusters (const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence, bool report_progress) +local_clusters::build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence, bool report_progress) { static std::string desc = tl::to_string (tr ("Building local clusters")); - db::box_scanner > bs (report_progress, desc); - typename T::tag object_tag; + db::box_scanner > bs (report_progress, desc); db::box_convert bc; + addressable_shape_delivery heap; + attr_accessor attr; + db::ShapeIterator::flags_type shape_flags = get_shape_flags () (attr_equivalence != 0 /*with attributes*/); for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) { const db::Shapes &shapes = cell.shapes (*l); for (db::Shapes::shape_iterator s = shapes.begin (shape_flags); ! s.at_end (); ++s) { - bs.insert (s->basic_ptr (object_tag), std::make_pair (*l, (unsigned int) s->prop_id ())); + bs.insert (heap (*s), std::make_pair (*l, attr (*s))); } } @@ -916,9 +1050,9 @@ local_clusters::build_clusters (const db::Cell &cell, db::ShapeIterator::flag template void -local_clusters::apply_attr_equivalences (const tl::equivalence_clusters &attr_equivalence) +local_clusters::apply_attr_equivalences (const tl::equivalence_clusters &attr_equivalence) { - tl::equivalence_clusters eq; + tl::equivalence_clusters eq; // collect all local attributes (the ones which are present in attr_equivalence) into "eq" // and form equivalences for multi-attribute clusters. @@ -939,18 +1073,18 @@ local_clusters::apply_attr_equivalences (const tl::equivalence_clusters::cluster_id_type, std::set > c2c; + std::map::cluster_id_type, std::set > c2c; for (const_iterator c = begin (); c != end (); ++c) { for (typename local_cluster::attr_iterator a = c->begin_attr (); a != c->end_attr (); ++a) { - tl::equivalence_clusters::cluster_id_type cl = attr_equivalence.cluster_id (*a); + tl::equivalence_clusters::cluster_id_type cl = attr_equivalence.cluster_id (*a); if (cl > 0) { c2c [cl].insert (c->id ()); } } } - for (std::map::cluster_id_type, std::set >::const_iterator c = c2c.begin (); c != c2c.end (); ++c) { + for (std::map::cluster_id_type, std::set >::const_iterator c = c2c.begin (); c != c2c.end (); ++c) { if (c->second.size () > 1) { std::set::const_iterator cl0 = c->second.begin (); std::set::const_iterator cl = cl0; @@ -962,6 +1096,7 @@ local_clusters::apply_attr_equivalences (const tl::equivalence_clusters; template class DB_PUBLIC local_clusters; template class DB_PUBLIC local_clusters; @@ -984,6 +1119,7 @@ connected_clusters_iterator::connected_clusters_iterator (const connected_clu } // explicit instantiations +template class DB_PUBLIC connected_clusters_iterator; template class DB_PUBLIC connected_clusters_iterator; template class DB_PUBLIC connected_clusters_iterator; @@ -1053,6 +1189,7 @@ connected_clusters::find_cluster_with_connection (const ClusterInstance &inst } // explicit instantiations +template class DB_PUBLIC connected_clusters; template class DB_PUBLIC connected_clusters; template class DB_PUBLIC connected_clusters; @@ -1133,11 +1270,11 @@ void hier_clusters::clear () template void -hier_clusters::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map > *attr_equivalence, const std::set *breakout_cells) +hier_clusters::build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map > *attr_equivalence, const std::set *breakout_cells) { clear (); cell_clusters_box_converter cbc (layout, *this); - do_build (cbc, layout, cell, shape_flags, conn, attr_equivalence, breakout_cells); + do_build (cbc, layout, cell, conn, attr_equivalence, breakout_cells); } namespace @@ -1939,7 +2076,7 @@ hier_clusters::propagate_cluster_inst (const db::Layout &layout, const db::Ce template void -hier_clusters::do_build (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map > *attr_equivalence, const std::set *breakout_cells) +hier_clusters::do_build (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map > *attr_equivalence, const std::set *breakout_cells) { tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Computing shape clusters"))); @@ -1957,8 +2094,8 @@ hier_clusters::do_build (cell_clusters_box_converter &cbc, const db::Layou // look for the net label joining spec - for the top cell the "top_cell_index" entry is looked for. // If there is no such entry or the cell is not the top cell, look for the entry by cell index. - std::map >::const_iterator ae; - const tl::equivalence_clusters *ec = 0; + std::map >::const_iterator ae; + const tl::equivalence_clusters *ec = 0; if (attr_equivalence) { if (*c == cell.cell_index ()) { ae = attr_equivalence->find (top_cell_index); @@ -1974,7 +2111,7 @@ hier_clusters::do_build (cell_clusters_box_converter &cbc, const db::Layou } } - build_local_cluster (layout, layout.cell (*c), shape_flags, conn, ec); + build_local_cluster (layout, layout.cell (*c), conn, ec); ++progress; @@ -2021,7 +2158,7 @@ hier_clusters::do_build (cell_clusters_box_converter &cbc, const db::Layou template void -hier_clusters::build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence) +hier_clusters::build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence) { std::string msg = tl::to_string (tr ("Computing local clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ())); if (tl::verbosity () >= m_base_verbosity + 20) { @@ -2030,7 +2167,7 @@ hier_clusters::build_local_cluster (const db::Layout &layout, const db::Cell tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 20, msg); connected_clusters &local = m_per_cell_clusters [cell.cell_index ()]; - local.build_clusters (cell, shape_flags, conn, attr_equivalence, true); + local.build_clusters (cell, conn, attr_equivalence, true); } template @@ -2336,6 +2473,7 @@ hier_clusters::return_to_hierarchy (db::Layout &layout, const std::map; template class DB_PUBLIC hier_clusters; template class DB_PUBLIC hier_clusters; @@ -2460,6 +2598,7 @@ void recursive_cluster_shape_iterator::down (db::cell_index_type ci, typename } // explicit instantiations +template class DB_PUBLIC recursive_cluster_shape_iterator; template class DB_PUBLIC recursive_cluster_shape_iterator; template class DB_PUBLIC recursive_cluster_shape_iterator; @@ -2533,6 +2672,7 @@ void recursive_cluster_iterator::down (db::cell_index_type ci, typename db::l } // explicit instantiations +template class DB_PUBLIC recursive_cluster_iterator; template class DB_PUBLIC recursive_cluster_iterator; template class DB_PUBLIC recursive_cluster_iterator; @@ -2614,6 +2754,7 @@ incoming_cluster_connections::ensure_computed_parent (db::cell_index_type ci) } // explicit instantiations +template class DB_PUBLIC incoming_cluster_connections; template class DB_PUBLIC incoming_cluster_connections; template class DB_PUBLIC incoming_cluster_connections; diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index 197ae8a0e..577eef944 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -505,7 +505,7 @@ public: * cluster joining may happen in this case, because multi-attribute * assignment might create connections too. */ - void build_clusters (const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence = 0, bool report_progress = false); + void build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence = 0, bool report_progress = false); /** * @brief Creates and inserts a new clusters @@ -540,7 +540,7 @@ private: tree_type m_clusters; size_t m_next_dummy_id; - void apply_attr_equivalences (const tl::equivalence_clusters &attr_equivalence); + void apply_attr_equivalences (const tl::equivalence_clusters &attr_equivalence); }; /** @@ -998,7 +998,7 @@ public: /** * @brief Builds a hierarchy of clusters from a cell hierarchy and given connectivity */ - void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map > *attr_equivalence = 0, const std::set *breakout_cells = 0); + void build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map > *attr_equivalence = 0, const std::set *breakout_cells = 0); /** * @brief Gets the connected clusters for a given cell @@ -1036,10 +1036,10 @@ public: size_t propagate_cluster_inst (const db::Layout &layout, const Cell &cell, const ClusterInstance &ci, db::cell_index_type parent_ci, bool with_self); private: - void build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence); + void build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence); void build_hier_connections (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set *breakout_cells, instance_interaction_cache_type &instance_interaction_cache); void build_hier_connections_for_cells (cell_clusters_box_converter &cbc, const db::Layout &layout, const std::vector &cells, const db::Connectivity &conn, const std::set *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache); - void do_build (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map > *attr_equivalence, const std::set *breakout_cells); + void do_build (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map > *attr_equivalence, const std::set *breakout_cells); std::map > m_per_cell_clusters; int m_base_verbosity; @@ -1335,6 +1335,39 @@ private: void ensure_computed_parent (db::cell_index_type ci) const; }; +/** + * @brief A helper function generating an attribute ID from a property ID + * This function is used to provide a generic attribute wrapping a property ID and a text ID. + */ +inline size_t prop_id_to_attr (db::properties_id_type id) +{ + return size_t (id) * 2; +} + +/** + * @brief Gets a value indicating whether the attribute is a property ID + */ +inline bool is_prop_id_attr (size_t attr) +{ + return (attr & 1) == 0; +} + +/** + * @brief Gets the property ID from an attribute + */ +inline db::properties_id_type prop_id_from_attr (size_t attr) +{ + return attr / 2; +} + +/** + * @brief A helper function generating an attribute from a StringRef + */ +inline size_t text_ref_to_attr (const db::Text *tr) +{ + return size_t (tr) * 2 + 1; +} + } #endif diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 2db262ac4..674f81430 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -157,29 +157,6 @@ public: } }; -template <> -class shape_reference_translator -{ -public: - typedef db::Text shape_type; - - shape_reference_translator (db::Layout * /*target_layout*/) - { - // .. nothing yet .. - } - - const shape_type &operator() (const shape_type &s) const - { - return s; - } - - template - shape_type operator() (const shape_type &s, const Trans &tr) const - { - return s.transformed (tr); - } -}; - template class shape_reference_translator_with_trans_from_shape_ref { @@ -656,11 +633,11 @@ shape_interactions::intruder_shape (unsigned int id) const template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; -template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; -template class DB_PUBLIC shape_interactions; -template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; // --------------------------------------------------------------------------------------------- // Helper classes for the LocalProcessor @@ -683,7 +660,7 @@ inline unsigned int shape_flags () } template <> -inline unsigned int shape_flags () +inline unsigned int shape_flags () { return db::ShapeIterator::Texts; } @@ -1780,15 +1757,15 @@ 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; 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/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc index 5ea489b02..35424cabc 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -706,7 +706,8 @@ void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape // --------------------------------------------------------------------------------------------- -TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver () +TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout) + : mp_layout (layout) { // .. nothing yet .. } @@ -714,10 +715,10 @@ TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeRece void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target) { if (shape.is_text ()) { - db::Text t; - shape.text (t); - t.transform (trans); - target->insert (t); + // NOTE: we intentionally skip all the text attributes (font etc.) here because in the context + // of a text collections we're only interested in the locations. + db::Text t (shape.text_string (), shape.text_trans ()); + target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ())); } } diff --git a/src/db/db/dbHierarchyBuilder.h b/src/db/db/dbHierarchyBuilder.h index 9b115bb05..2ddd6fe22 100644 --- a/src/db/db/dbHierarchyBuilder.h +++ b/src/db/db/dbHierarchyBuilder.h @@ -196,11 +196,14 @@ class DB_PUBLIC TextBuildingHierarchyBuilderShapeReceiver : public HierarchyBuilderShapeReceiver { public: - TextBuildingHierarchyBuilderShapeReceiver (); + TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout); virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } + +private: + db::Layout *mp_layout; }; /** diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index dd39be48e..96aaf475e 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -558,6 +558,14 @@ public: return m_string_repository; } + /** + * @brief Accessor to the string repository (const version) + */ + const StringRepository &string_repository () const + { + return m_string_repository; + } + /** * @brief Accessor to the shape repository */ @@ -566,6 +574,14 @@ public: return m_shape_repository; } + /** + * @brief Accessor to the shape repository (const version) + */ + const GenericRepository &shape_repository () const + { + return m_shape_repository; + } + /** * @brief Accessor to the properties repository */ diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index d362aa4c5..479e67ed0 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -206,7 +206,7 @@ void LayoutToNetlist::link_nets (const db::Net *net, const db::Net *with) return; } - connected_clusters &clusters = m_net_clusters.clusters_per_cell (net->circuit ()->cell_index ()); + connected_clusters &clusters = m_net_clusters.clusters_per_cell (net->circuit ()->cell_index ()); clusters.join_cluster_with (net->cluster_id (), with->cluster_id ()); } @@ -221,7 +221,7 @@ size_t LayoutToNetlist::link_net_to_parent_circuit (const Net *subcircuit_net, C db::CplxTrans dbu_trans (internal_layout ()->dbu ()); db::ICplxTrans trans = dbu_trans.inverted () * dtrans * dbu_trans; - connected_clusters &parent_net_clusters = m_net_clusters.clusters_per_cell (parent_circuit->cell_index ()); + connected_clusters &parent_net_clusters = m_net_clusters.clusters_per_cell (parent_circuit->cell_index ()); size_t id = parent_net_clusters.insert_dummy (); @@ -613,49 +613,84 @@ namespace } template -static bool deliver_shape (const db::PolygonRef &, StopOnFirst, const Tr &, db::properties_id_type) +static bool deliver_shape (const db::NetShape &, StopOnFirst, const Tr &, db::properties_id_type) { return false; } template -static bool deliver_shape (const db::PolygonRef &pr, db::Region ®ion, const Tr &tr, db::properties_id_type /*propid*/) +static bool deliver_shape (const db::NetShape &s, db::Region ®ion, const Tr &tr, db::properties_id_type /*propid*/) { - if (pr.obj ().is_box ()) { - region.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); - } else { - region.insert (pr.obj ().transformed (pr.trans ()).transformed (tr)); + if (s.type () == db::NetShape::Polygon) { + + db::PolygonRef pr = s.polygon_ref (); + + if (pr.obj ().is_box ()) { + region.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); + } else { + region.insert (pr.obj ().transformed (pr.trans ()).transformed (tr)); + } + } + return true; } template -static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr, db::properties_id_type propid) +static bool deliver_shape (const db::NetShape &s, db::Shapes &shapes, const Tr &tr, db::properties_id_type propid) { - if (pr.obj ().is_box ()) { - if (propid) { - shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid)); + if (s.type () == db::NetShape::Polygon) { + + db::PolygonRef pr = s.polygon_ref (); + + if (pr.obj ().is_box ()) { + if (propid) { + shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid)); + } else { + shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); + } } else { - shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); + db::Layout *layout = shapes.layout (); + if (layout) { + db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()); + if (propid) { + shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid)); + } else { + shapes.insert (polygon_ref); + } + } else { + db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr)); + if (propid) { + shapes.insert (db::PolygonWithProperties (polygon, propid)); + } else { + shapes.insert (polygon); + } + } } - } else { + + } else if (s.type () == db::NetShape::Text) { + + db::TextRef pr = s.text_ref (); + db::Layout *layout = shapes.layout (); if (layout) { - db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()); + db::TextRef text_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()); if (propid) { - shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid)); + shapes.insert (db::TextRefWithProperties (text_ref, propid)); } else { - shapes.insert (polygon_ref); + shapes.insert (text_ref); } } else { - db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr)); + db::Text text (pr.obj ().transformed (pr.trans ()).transformed (tr)); if (propid) { - shapes.insert (db::PolygonWithProperties (polygon, propid)); + shapes.insert (db::TextWithProperties (text, propid)); } else { - shapes.insert (polygon); + shapes.insert (text); } } + } + return true; } @@ -759,7 +794,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout & if (net_cell_name_prefix) { - const db::connected_clusters &ccl = m_net_clusters.clusters_per_cell (ci); + const db::connected_clusters &ccl = m_net_clusters.clusters_per_cell (ci); bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty (); if (! any_connections) { @@ -805,8 +840,8 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout & db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ()); db::ICplxTrans tr_mag (tr.mag ()); - const db::connected_clusters &clusters = m_net_clusters.clusters_per_cell (ci); - typedef db::connected_clusters::connections_type connections_type; + const db::connected_clusters &clusters = m_net_clusters.clusters_per_cell (ci); + typedef db::connected_clusters::connections_type connections_type; const connections_type &connections = clusters.connections_for_cluster (cid); for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) { @@ -1007,13 +1042,13 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoi return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point); } -size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path) +size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path) { db::Box local_box = trans * test_cluster.bbox (); - const db::local_clusters &lcc = net_clusters ().clusters_per_cell (cell->cell_index ()); - for (db::local_clusters::touching_iterator i = lcc.begin_touching (local_box); ! i.at_end (); ++i) { - const db::local_cluster &lc = *i; + const db::local_clusters &lcc = net_clusters ().clusters_per_cell (cell->cell_index ()); + for (db::local_clusters::touching_iterator i = lcc.begin_touching (local_box); ! i.at_end (); ++i) { + const db::local_cluster &lc = *i; if (lc.interacts (test_cluster, trans, m_conn)) { return lc.id (); } @@ -1053,7 +1088,7 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin // Prepare a test cluster db::Box box (point - db::Vector (1, 1), point + db::Vector (1, 1)); db::GenericRepository sr; - db::local_cluster test_cluster; + db::local_cluster test_cluster; test_cluster.add (db::PolygonRef (db::Polygon (box), sr), layer); std::vector inst_path; @@ -1155,12 +1190,12 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg for (db::Layout::bottom_up_const_iterator cid = ly.begin_bottom_up (); cid != ly.end_bottom_up (); ++cid) { - const connected_clusters &clusters = m_net_clusters.clusters_per_cell (*cid); + const connected_clusters &clusters = m_net_clusters.clusters_per_cell (*cid); if (clusters.empty ()) { continue; } - for (connected_clusters::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) { + for (connected_clusters::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) { if (! clusters.is_root (*c)) { continue; diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 6f8771644..f92632bd8 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -522,7 +522,7 @@ public: * NOTE: the layer and cell indexes used inside this structure refer to the * internal layout. */ - const db::hier_clusters &net_clusters () const + const db::hier_clusters &net_clusters () const { return m_net_clusters; } @@ -530,7 +530,7 @@ public: /** * @brief Gets the hierarchical shape clusters derived in the net extraction (non-conver version) */ - db::hier_clusters &net_clusters () + db::hier_clusters &net_clusters () { return m_net_clusters; } @@ -744,7 +744,7 @@ private: tl::weak_ptr mp_dss; unsigned int m_layout_index; db::Connectivity m_conn; - db::hier_clusters m_net_clusters; + db::hier_clusters m_net_clusters; std::auto_ptr mp_netlist; std::set m_dlrefs; std::map m_named_regions; @@ -786,7 +786,7 @@ private: void init (); void ensure_netlist (); - size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path); + size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path); void build_net_rec (const db::Net &net, db::Layout &target, cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const; void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const; void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const; diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index 599b08aa1..877f9842d 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -524,7 +524,7 @@ LayoutToNetlistStandardReader::read_polygon () } void -LayoutToNetlistStandardReader::read_geometries (db::NetlistObject *obj, Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &lc, db::Cell &cell) +LayoutToNetlistStandardReader::read_geometries (db::NetlistObject *obj, Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &lc, db::Cell &cell) { m_ref = db::Point (); @@ -561,8 +561,8 @@ LayoutToNetlistStandardReader::read_net (db::Netlist * /*netlist*/, db::LayoutTo if (l2n) { - db::connected_clusters &cc = l2n->net_clusters ().clusters_per_cell (circuit->cell_index ()); - db::local_cluster &lc = *cc.insert (); + db::connected_clusters &cc = l2n->net_clusters ().clusters_per_cell (circuit->cell_index ()); + db::local_cluster &lc = *cc.insert (); net->set_cluster_id (lc.id ()); db::Cell &cell = l2n->internal_layout ()->cell (circuit->cell_index ()); @@ -1025,8 +1025,8 @@ LayoutToNetlistStandardReader::read_abstract_terminal (db::LayoutToNetlist *l2n, if (l2n) { - db::connected_clusters &cc = l2n->net_clusters ().clusters_per_cell (dm->cell_index ()); - db::local_cluster &lc = *cc.insert (); + db::connected_clusters &cc = l2n->net_clusters ().clusters_per_cell (dm->cell_index ()); + db::local_cluster &lc = *cc.insert (); dm->set_cluster_id_for_terminal (tid, lc.id ()); db::Cell &cell = l2n->internal_layout ()->cell (dm->cell_index ()); diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index ebd3be9c5..860d7f714 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -143,7 +143,7 @@ protected: void read_property (db::NetlistObject *obj); db::Polygon read_polygon (); db::Box read_rect (); - void read_geometries (db::NetlistObject *obj, Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &lc, db::Cell &cell); + void read_geometries (db::NetlistObject *obj, Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &lc, db::Cell &cell); db::Point read_point (); private: diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 6a211129b..ad1531e13 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -397,11 +397,16 @@ void std_writer_impl::reset_geometry_ref () } template -void std_writer_impl::write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname, bool relative) +void std_writer_impl::write (const db::NetShape *s, const db::ICplxTrans &tr, const std::string &lname, bool relative) { - db::ICplxTrans t = tr * db::ICplxTrans (s->trans ()); + if (s->type () != db::NetShape::Polygon) { + return; + } - const db::Polygon &poly = s->obj (); + db::PolygonRef pr = s->polygon_ref (); + db::ICplxTrans t = tr * db::ICplxTrans (pr.trans ()); + + const db::Polygon &poly = pr.obj (); if (poly.is_box ()) { db::Box box = t * poly.box (); @@ -435,7 +440,7 @@ bool std_writer_impl::new_cell (cell_index_type ci) const template void std_writer_impl::write (const db::Net &net, unsigned int id, const std::string &indent) { - const db::hier_clusters &clusters = mp_l2n->net_clusters (); + const db::hier_clusters &clusters = mp_l2n->net_clusters (); const db::Circuit *circuit = net.circuit (); const db::Connectivity &conn = mp_l2n->connectivity (); @@ -450,7 +455,7 @@ void std_writer_impl::write (const db::Net &net, unsigned int id, const st db::cell_index_type cci = circuit->cell_index (); db::cell_index_type prev_ci = cci; - for (db::recursive_cluster_shape_iterator si (clusters, *l, cci, net.cluster_id (), this); ! si.at_end (); ) { + for (db::recursive_cluster_shape_iterator si (clusters, *l, cci, net.cluster_id (), this); ! si.at_end (); ) { // NOTE: we don't recursive into circuits which will later be output. However, as circuits may // vanish in "purge" but the clusters will still be there we need to recursive into clusters from @@ -570,7 +575,7 @@ void std_writer_impl::write (const db::DeviceAbstract &device_abstract, co { const std::vector &td = device_abstract.device_class ()->terminal_definitions (); - const db::hier_clusters &clusters = mp_l2n->net_clusters (); + const db::hier_clusters &clusters = mp_l2n->net_clusters (); const db::Connectivity &conn = mp_l2n->connectivity (); for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { @@ -587,8 +592,8 @@ void std_writer_impl::write (const db::DeviceAbstract &device_abstract, co continue; } - const db::local_cluster &lc = clusters.clusters_per_cell (device_abstract.cell_index ()).cluster_by_id (cid); - for (db::local_cluster::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) { + const db::local_cluster &lc = clusters.clusters_per_cell (device_abstract.cell_index ()).cluster_by_id (cid); + for (db::local_cluster::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) { *mp_stream << indent << indent2; write (s.operator-> (), db::ICplxTrans (), name_for_layer (mp_l2n, *l), true); diff --git a/src/db/db/dbLayoutToNetlistWriter.h b/src/db/db/dbLayoutToNetlistWriter.h index 08cc82196..5065c61a8 100644 --- a/src/db/db/dbLayoutToNetlistWriter.h +++ b/src/db/db/dbLayoutToNetlistWriter.h @@ -41,6 +41,7 @@ class DeviceAbstract; class Net; class Netlist; class LayoutToNetlist; +class NetShape; namespace l2n_std_format { @@ -75,7 +76,7 @@ private: void write (const db::SubCircuit &subcircuit, std::map &net2id, const std::string &indent); void write (const db::Device &device, std::map &net2id, const std::string &indent); void write (const db::DeviceAbstract &device_abstract, const std::string &indent); - void write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname, bool relative); + void write (const db::NetShape *s, const db::ICplxTrans &tr, const std::string &lname, bool relative); void write (const db::DCplxTrans &trans); void reset_geometry_ref (); diff --git a/src/db/db/dbNetShape.cc b/src/db/db/dbNetShape.cc new file mode 100644 index 000000000..ba3564754 --- /dev/null +++ b/src/db/db/dbNetShape.cc @@ -0,0 +1,218 @@ +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbNetShape.h" +#include "dbShapes.h" +#include "dbPolygonTools.h" + +namespace db { + +NetShape::NetShape () + : m_ptr (0), m_dx (0), m_dy (0) +{ } + +NetShape::NetShape (const db::PolygonRef &pr) +{ + m_ptr = size_t (&pr.obj ()) + 1; + m_dx = pr.trans ().disp ().x (); + m_dy = pr.trans ().disp ().y (); +} + +NetShape::NetShape (const db::Polygon &poly, db::GenericRepository &repo) +{ + db::PolygonRef pr (poly, repo); + m_ptr = size_t (&pr.obj ()) + 1; + m_dx = pr.trans ().disp ().x (); + m_dy = pr.trans ().disp ().y (); +} + +NetShape::NetShape (const db::TextRef &tr) +{ + m_ptr = size_t (&tr.obj ()); + m_dx = tr.trans ().disp ().x (); + m_dy = tr.trans ().disp ().y (); +} + +NetShape::NetShape (const db::Text &text, db::GenericRepository &repo) +{ + db::TextRef tr (text, repo); + m_ptr = size_t (&tr.obj ()); + m_dx = tr.trans ().disp ().x (); + m_dy = tr.trans ().disp ().y (); +} + +NetShape::shape_type NetShape::type () const +{ + if (m_ptr == 0) { + return None; + } else if ((m_ptr & 1) != 0) { + return Polygon; + } else { + return Text; + } +} + +db::PolygonRef NetShape::polygon_ref () const +{ + if ((size_t (m_ptr) & 1) != 0) { + return db::PolygonRef (reinterpret_cast (m_ptr - 1), db::Disp (db::Vector (m_dx, m_dy))); + } + tl_assert (false); +} + +db::TextRef NetShape::text_ref () const +{ + if ((size_t (m_ptr) & 1) == 0) { + return db::TextRef (reinterpret_cast (m_ptr), db::Disp (db::Vector (m_dx, m_dy))); + } + tl_assert (false); +} + +void NetShape::transform (const db::Disp &tr) +{ + m_dx += tr.disp ().x (); + m_dy += tr.disp ().y (); +} + +NetShape::box_type NetShape::bbox () const +{ + if ((m_ptr & 1) != 0) { + return polygon_ref ().box (); + } else if (m_ptr != 0) { + return text_ref ().box (); + } else { + return box_type (); + } +} + +void NetShape::insert_into (db::Shapes &shapes) const +{ + if ((m_ptr & 1) != 0) { + shapes.insert (polygon_ref ()); + } else if (m_ptr != 0) { + shapes.insert (text_ref ()); + } +} + +void NetShape::insert_into (db::Shapes &shapes, db::properties_id_type pi) const +{ + if ((m_ptr & 1) != 0) { + shapes.insert (db::PolygonRefWithProperties (polygon_ref (), pi)); + } else if (m_ptr != 0) { + shapes.insert (db::TextRefWithProperties (text_ref (), pi)); + } +} + +bool NetShape::interacts_with (const db::NetShape &other) const +{ + if (m_ptr == 0 || other.m_ptr == 0 || ! bbox ().touches (other.bbox ())) { + return false; + } + + if ((m_ptr & 1) != 0) { + + if ((other.m_ptr & 1) != 0) { + + // Polygon vs. polygon + db::PolygonRef pr_other = other.polygon_ref (); + db::PolygonRef pr = polygon_ref (); + db::Polygon p = pr_other.obj ().transformed (pr.trans ().inverted () * pr_other.trans ()); + return db::interact_pp (pr.obj (), p); + + } else { + + // NOTE: we assume that the text ref's target is at 0,0 + db::PolygonRef pr = polygon_ref (); + db::Point pt = db::Point (other.m_dx, other.m_dy) - pr.trans ().disp (); + return db::inside_poly (pr.obj ().begin_edge (), pt) >= 0; + + } + + } else { + + if ((other.m_ptr & 1) == 0) { + + // Text vs. text + return m_dx == other.m_dx && m_dy == other.m_dy; + + } else { + + // NOTE: we assume that the text ref's target is at 0,0 + db::PolygonRef pr_other = other.polygon_ref (); + db::Point pt = db::Point (m_dx, m_dy) - pr_other.trans ().disp (); + return db::inside_poly (pr_other.obj ().begin_edge (), pt) >= 0; + + } + + } +} + +template +bool NetShape::interacts_with_transformed (const db::NetShape &other, const Tr &trans) const +{ + if (m_ptr == 0 || other.m_ptr == 0 || ! bbox ().touches (other.bbox ().transformed (trans))) { + return false; + } + + if ((m_ptr & 1) != 0) { + + if ((other.m_ptr & 1) != 0) { + + // Polygon vs. polygon + db::PolygonRef pr_other = other.polygon_ref (); + db::PolygonRef pr = polygon_ref (); + db::Polygon p = pr_other.obj ().transformed (Tr (pr.trans ().inverted ()) * trans * Tr (pr_other.trans ())); + return db::interact_pp (pr.obj (), p); + + } else { + + // NOTE: we assume that the text ref's target is at 0,0 + db::PolygonRef pr = polygon_ref (); + db::Point pt = trans * db::Point (other.m_dx, other.m_dy) - pr.trans ().disp (); + return db::inside_poly (pr.obj ().begin_edge (), pt) >= 0; + + } + + } else { + + if ((other.m_ptr & 1) == 0) { + + // Text vs. text + db::Point pt = trans * db::Point (other.m_dx, other.m_dy); + return db::Point (m_dx, m_dy) == pt; + + } else { + + // NOTE: we assume that the text ref's target is at 0,0 + db::PolygonRef pr_other = other.polygon_ref (); + db::Point pt = trans.inverted () * db::Point (m_dx, m_dy) - pr_other.trans ().disp (); + return db::inside_poly (pr_other.obj ().begin_edge (), pt) >= 0; + + } + + } +} + +// explicit instantiations +template bool NetShape::interacts_with_transformed (const db::NetShape &other, const db::ICplxTrans &trans) const; +template bool NetShape::interacts_with_transformed (const db::NetShape &other, const db::Trans &trans) const; + +} diff --git a/src/db/db/dbNetShape.h b/src/db/db/dbNetShape.h new file mode 100644 index 000000000..3ee5c2e4a --- /dev/null +++ b/src/db/db/dbNetShape.h @@ -0,0 +1,178 @@ +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbNetShape +#define HDR_dbNetShape + +#include "dbPolygon.h" +#include "dbText.h" +#include "dbShapeRepository.h" +#include "dbBoxConvert.h" + +namespace db { + +class Shapes; + +/** + * @brief Provides a union of a PolygonRef and a TextRef + * + * This object is used in the netlist extractor and represents either a polygon or a text. + * The TextRef shall utilize a StringRef to represent the string. + */ +class DB_PUBLIC NetShape +{ +public: + enum shape_type { None, Text, Polygon }; + + typedef db::Point point_type; + typedef db::Box box_type; + typedef db::Coord coord_type; + typedef db::Disp trans_type; + + /** + * @brief Default constructor + */ + NetShape (); + + /** + * @brief A NetShape object representing a PolygonRef + */ + NetShape (const db::PolygonRef &pr); + + /** + * @brief A NetShape object representing a Polygon from the given shape repository + */ + NetShape (const db::Polygon &poly, db::GenericRepository &repo); + + /** + * @brief A NetShape object representing a TextRef + */ + NetShape (const db::TextRef &tr); + + /** + * @brief A NetShape object representing a Text from the given shape repository + */ + NetShape (const db::Text &text, db::GenericRepository &repo); + + /** + * @brief Gets a code indicating the type of object stored herein + */ + shape_type type () const; + + /** + * @brief Gets the PolygonRef object + * Asserts if the object stored is not a polygon. + */ + db::PolygonRef polygon_ref () const; + + /** + * @brief Gets the TextRef object + * Asserts if the object stored is not a text. + */ + db::TextRef text_ref () const; + + /** + * @brief In-place transformation + */ + void transform (const db::Disp &tr); + + /** + * @brief Equality + */ + bool operator== (const NetShape &net_shape) const + { + return m_ptr == net_shape.m_ptr && m_dx == net_shape.m_dx && m_dy == net_shape.m_dy; + } + + /** + * @brief Inequality + */ + bool operator!= (const NetShape &net_shape) const + { + return ! operator== (net_shape); + } + + /** + * @brief Less operator + */ + bool operator< (const NetShape &net_shape) const + { + if (m_ptr != net_shape.m_ptr) { + return m_ptr < net_shape.m_ptr; + } + if (m_dx != net_shape.m_dx) { + return m_dx < net_shape.m_dx; + } + return m_dy < net_shape.m_dy; + } + + /** + * @brief Gets the bounding box of the object + */ + box_type bbox () const; + + /** + * @brief Inserts the object into a Shapes collection + */ + void insert_into (db::Shapes &shapes) const; + + /** + * @brief Inserts the object into a Shapes collection with the given properties ID + */ + void insert_into (db::Shapes &shapes, db::properties_id_type pi) const; + + /** + * @brief Returns true if the object interacts with another NetShape object + */ + bool interacts_with (const db::NetShape &other) const; + + /** + * @brief Returns true if the object interacts with another NetShape object after transforming it + */ + template + bool interacts_with_transformed (const db::NetShape &other, const Tr &trans) const; + +public: + size_t m_ptr; + coord_type m_dx, m_dy; +}; + +/** + * @brief A box converter implementation for NetShape + */ +template <> +struct box_convert +{ + typedef db::NetShape::box_type box_type; + typedef db::NetShape::coord_type coord_type; + typedef db::complex_bbox_tag complexity; + + box_type operator() (const db::NetShape &net_shape) const + { + return net_shape.bbox (); + } +}; + +} + +#endif + diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 0206b2725..b022e9f5e 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -119,9 +119,12 @@ void NetlistDeviceExtractor::initialize (db::Netlist *nl) setup (); } -static void insert_into_region (const db::PolygonRef &s, const db::ICplxTrans &tr, db::Region ®ion) +static void insert_into_region (const db::NetShape &s, const db::ICplxTrans &tr, db::Region ®ion) { - region.insert (s.obj ().transformed (tr * db::ICplxTrans (s.trans ()))); + if (s.type () == db::NetShape::Polygon) { + db::PolygonRef pr = s.polygon_ref (); + region.insert (pr.obj ().transformed (tr * db::ICplxTrans (pr.trans ()))); + } } void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layout_index, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters, double device_scaling) @@ -207,8 +210,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db: { tl_assert (layers.size () == m_layer_definitions.size ()); - typedef db::PolygonRef shape_type; - db::ShapeIterator::flags_type shape_iter_flags = db::ShapeIterator::Polygons; + typedef db::NetShape shape_type; mp_layout = &layout; m_layers = layers; @@ -247,7 +249,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db: db::Connectivity device_conn = get_connectivity (layout, layers); db::hier_clusters device_clusters; - device_clusters.build (layout, cell, shape_iter_flags, device_conn, 0, breakout_cells); + device_clusters.build (layout, cell, device_conn, 0, breakout_cells); tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Extracting devices"))); @@ -365,12 +367,12 @@ void NetlistDeviceExtractor::push_new_devices (const db::Vector &disp_cache) DeviceCellKey key; for (geometry_per_terminal_type::const_iterator t = d->second.second.begin (); t != d->second.second.end (); ++t) { - std::map > > = key.geometry [t->first]; + std::map > > = key.geometry [t->first]; for (geometry_per_layer_type::const_iterator l = t->second.begin (); l != t->second.end (); ++l) { - std::set &gl = gt [l->first]; - for (std::vector::const_iterator p = l->second.begin (); p != l->second.end (); ++p) { - db::PolygonRef pr = *p; - pr.transform (db::PolygonRef::trans_type (-disp)); + std::set &gl = gt [l->first]; + for (std::vector::const_iterator p = l->second.begin (); p != l->second.end (); ++p) { + db::NetShape pr = *p; + pr.transform (db::NetShape::trans_type (-disp)); gl.insert (pr); } } @@ -411,10 +413,10 @@ void NetlistDeviceExtractor::push_new_devices (const db::Vector &disp_cache) for (geometry_per_layer_type::const_iterator l = t->second.begin (); l != t->second.end (); ++l) { db::Shapes &shapes = device_cell.shapes (l->first); - for (std::vector::const_iterator s = l->second.begin (); s != l->second.end (); ++s) { - db::PolygonRef pr = *s; - pr.transform (db::PolygonRef::trans_type (-disp)); - shapes.insert (db::PolygonRefWithProperties (pr, pi)); + for (std::vector::const_iterator s = l->second.begin (); s != l->second.end (); ++s) { + db::NetShape pr = *s; + pr.transform (db::NetShape::trans_type (-disp)); + pr.insert_into (shapes, pi); } } @@ -542,10 +544,10 @@ void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id std::pair &dd = m_new_devices[device->id ()]; dd.first = device; - std::vector &geo = dd.second[terminal_id][layer_index]; + std::vector &geo = dd.second[terminal_id][layer_index]; for (db::Region::const_iterator p = region.begin_merged (); !p.at_end (); ++p) { - geo.push_back (db::PolygonRef (*p, mp_layout->shape_repository ())); + geo.push_back (db::NetShape (*p, mp_layout->shape_repository ())); } } @@ -555,7 +557,7 @@ void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id tl_assert (geometry_index < m_layers.size ()); unsigned int layer_index = m_layers [geometry_index]; - db::PolygonRef pr (polygon, mp_layout->shape_repository ()); + db::NetShape pr (polygon, mp_layout->shape_repository ()); std::pair &dd = m_new_devices[device->id ()]; dd.first = device; dd.second[terminal_id][layer_index].push_back (pr); diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index 8141093eb..2cfc3c40e 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -29,6 +29,7 @@ #include "dbHierNetworkProcessor.h" #include "dbDeepShapeStore.h" #include "dbRegion.h" +#include "dbNetShape.h" #include "gsiObject.h" @@ -205,7 +206,7 @@ public: typedef std::vector layer_definitions; typedef layer_definitions::const_iterator layer_definitions_iterator; typedef std::map input_layers; - typedef db::hier_clusters hier_clusters_type; + typedef db::hier_clusters hier_clusters_type; /** * @brief Constructor @@ -260,8 +261,6 @@ public: * the nets later to associate nets with device terminals. * * The definition of the input layers is device class specific. - * - * NOTE: The extractor expects "PolygonRef" type layers. */ void extract (Layout &layout, Cell &cell, const std::vector &layers, Netlist *netlist, hier_clusters_type &clusters, double device_scaling = 1.0, const std::set *breakout_cells = 0); @@ -521,11 +520,11 @@ private: return false; } - std::map > > geometry; + std::map > > geometry; std::map parameters; }; - typedef std::map > geometry_per_layer_type; + typedef std::map > geometry_per_layer_type; typedef std::map geometry_per_terminal_type; tl::weak_ptr m_netlist; diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 539d7b7dd..bfe1fba9f 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -23,6 +23,7 @@ #include "dbNetlistExtractor.h" #include "dbDeepShapeStore.h" #include "dbNetlistDeviceExtractor.h" +#include "dbShapeRepository.h" #include "tlGlobPattern.h" namespace db @@ -50,9 +51,9 @@ void NetlistExtractor::set_include_floating_subcircuits (bool f) } static void -build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type net_name_id, const std::string &joined_net_names, tl::equivalence_clusters &eq) +build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type net_name_id, const std::string &joined_net_names, tl::equivalence_clusters &eq) { - std::map > prop_by_name; + std::map > prop_by_name; tl::GlobPattern jn_pattern (joined_net_names); for (db::PropertiesRepository::iterator i = layout->properties_repository ().begin (); i != layout->properties_repository ().end (); ++i) { @@ -60,15 +61,23 @@ build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type if (p->first == net_name_id) { std::string nn = p->second.to_string (); if (jn_pattern.match (nn)) { - prop_by_name [nn].insert (i->first); + prop_by_name [nn].insert (db::prop_id_to_attr (i->first)); } } } } - for (std::map >::const_iterator pn = prop_by_name.begin (); pn != prop_by_name.end (); ++pn) { - std::set::const_iterator p = pn->second.begin (); - std::set::const_iterator p0 = p; + const db::repository &text_repository = layout->shape_repository ().repository (db::object_tag ()); + for (db::repository::iterator t = text_repository.begin (); t != text_repository.end (); ++t) { + std::string nn = t->string (); + if (jn_pattern.match (nn)) { + prop_by_name [nn].insert (db::text_ref_to_attr (t.operator-> ())); + } + } + + for (std::map >::const_iterator pn = prop_by_name.begin (); pn != prop_by_name.end (); ++pn) { + std::set::const_iterator p = pn->second.begin (); + std::set::const_iterator p0 = p; while (p != pn->second.end ()) { eq.same (*p0, *p); ++p; @@ -93,9 +102,9 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo m_terminal_annot_name_id = mp_layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::terminal_id_property_name ()); m_device_annot_name_id = mp_layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_id_property_name ()); - // the big part: actually extract the nets + // build an attribute equivalence map which lists the "attribute IDs" which are identical in terms of net names - std::map > net_name_equivalence; + std::map > net_name_equivalence; if (m_text_annot_name_id.first) { if (! m_joined_net_names.empty ()) { build_net_name_equivalence (mp_layout, m_text_annot_name_id.second, m_joined_net_names, net_name_equivalence [hier_clusters_type::top_cell_index]); @@ -107,7 +116,10 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo } } } - mp_clusters->build (*mp_layout, *mp_cell, db::ShapeIterator::Polygons, conn, &net_name_equivalence); + + // the big part: actually extract the nets + + mp_clusters->build (*mp_layout, *mp_cell, conn, &net_name_equivalence); // reverse lookup for Circuit vs. cell index std::map circuits; @@ -181,7 +193,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo for (connected_clusters_type::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) { - const db::local_cluster &lc = clusters.cluster_by_id (*c); + const db::local_cluster &lc = clusters.cluster_by_id (*c); if (clusters.connections_for_cluster (*c).empty () && lc.empty ()) { // this is an entirely empty cluster so we skip it. // Such clusters are left over when joining clusters. @@ -204,8 +216,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo // add the global names as second priority if (net_names.empty ()) { - const db::local_cluster::global_nets &gn = lc.get_global_nets (); - for (db::local_cluster::global_nets::const_iterator g = gn.begin (); g != gn.end (); ++g) { + const db::local_cluster::global_nets &gn = lc.get_global_nets (); + for (db::local_cluster::global_nets::const_iterator g = gn.begin (); g != gn.end (); ++g) { net_names.insert (conn.global_net_name (*g)); } } @@ -250,7 +262,13 @@ NetlistExtractor::make_device_abstract_connections (db::DeviceAbstract *dm, cons for (local_cluster_type::attr_iterator a = dc->begin_attr (); a != dc->end_attr (); ++a) { - const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a); + if (! db::is_prop_id_attr (*a)) { + continue; + } + + db::properties_id_type pi = db::prop_id_from_attr (*a); + + const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (pi); for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { if (j->first == m_terminal_annot_name_id.second) { dm->set_cluster_id_for_terminal (j->second.to (), dc->id ()); @@ -282,7 +300,13 @@ void NetlistExtractor::collect_labels (const connected_clusters_type &clusters, const local_cluster_type &lc = clusters.cluster_by_id (cid); for (local_cluster_type::attr_iterator a = lc.begin_attr (); a != lc.end_attr (); ++a) { - const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a); + if (! db::is_prop_id_attr (*a)) { + continue; + } + + db::properties_id_type pi = db::prop_id_from_attr (*a); + + const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (pi); for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { if (m_text_annot_name_id.first && j->first == m_text_annot_name_id.second) { @@ -343,13 +367,19 @@ void NetlistExtractor::connect_devices (db::Circuit *circuit, continue; } - const db::local_cluster &dc = mp_clusters->clusters_per_cell (inst_cell_index).cluster_by_id (i->id ()); + const db::local_cluster &dc = mp_clusters->clusters_per_cell (inst_cell_index).cluster_by_id (i->id ()); // connect the net to the terminal of the device: take the terminal ID from the properties on the // device cluster for (local_cluster_type::attr_iterator a = dc.begin_attr (); a != dc.end_attr (); ++a) { - const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a); + if (! db::is_prop_id_attr (*a)) { + continue; + } + + db::properties_id_type pi = db::prop_id_from_attr (*a); + + const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (pi); for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { if (m_terminal_annot_name_id.first && j->first == m_terminal_annot_name_id.second) { diff --git a/src/db/db/dbNetlistExtractor.h b/src/db/db/dbNetlistExtractor.h index f25490d93..072253dc8 100644 --- a/src/db/db/dbNetlistExtractor.h +++ b/src/db/db/dbNetlistExtractor.h @@ -25,6 +25,7 @@ #include "dbCommon.h" #include "dbHierNetworkProcessor.h" +#include "dbNetShape.h" #include #include @@ -71,9 +72,9 @@ class DeviceAbstract; class DB_PUBLIC NetlistExtractor { public: - typedef db::hier_clusters hier_clusters_type; - typedef db::connected_clusters connected_clusters_type; - typedef db::local_cluster local_cluster_type; + typedef db::hier_clusters hier_clusters_type; + typedef db::connected_clusters connected_clusters_type; + typedef db::local_cluster local_cluster_type; /** * @brief NetExtractor constructor diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc index 6748fc954..f0ead2b95 100644 --- a/src/db/db/dbRegionUtils.cc +++ b/src/db/db/dbRegionUtils.cc @@ -353,23 +353,23 @@ template class region_to_edge_interaction_filter_base; // ------------------------------------------------------------------------------------- // RegionToTextInteractionFilterBase implementation -template -region_to_text_interaction_filter_base::region_to_text_interaction_filter_base (bool inverse) +template +region_to_text_interaction_filter_base::region_to_text_interaction_filter_base (bool inverse) : m_inverse (inverse) { // .. nothing yet .. } -template +template void -region_to_text_interaction_filter_base::preset (const OutputType *s) +region_to_text_interaction_filter_base::preset (const OutputType *s) { m_seen.insert (s); } -template +template void -region_to_text_interaction_filter_base::add (const db::Polygon *p, size_t, const db::Text *t, size_t) +region_to_text_interaction_filter_base::add (const db::Polygon *p, size_t, const TextType *t, size_t) { const OutputType *o = 0; tl::select (o, p, t); @@ -378,8 +378,7 @@ region_to_text_interaction_filter_base::add (const db::Polygon *p, s // A polygon and an text interact if the text is either inside completely // of at least one text of the polygon intersects with the text - db::Point pt; - pt += t->trans ().disp (); + db::Point pt = db::box_convert () (*t).p1 (); if (p->box ().contains (pt) && db::inside_poly (p->begin_edge (), pt) >= 0) { if (m_inverse) { m_seen.erase (o); @@ -392,9 +391,9 @@ region_to_text_interaction_filter_base::add (const db::Polygon *p, s } } -template +template void -region_to_text_interaction_filter_base::fill_output () +region_to_text_interaction_filter_base::fill_output () { for (typename std::set::const_iterator s = m_seen.begin (); s != m_seen.end (); ++s) { put (**s); @@ -402,8 +401,9 @@ region_to_text_interaction_filter_base::fill_output () } // explicit instantiations -template class region_to_text_interaction_filter_base; -template class region_to_text_interaction_filter_base; +template class region_to_text_interaction_filter_base; +template class region_to_text_interaction_filter_base; +template class region_to_text_interaction_filter_base; // ------------------------------------------------------------------------------------- // Polygon snapping diff --git a/src/db/db/dbRegionUtils.h b/src/db/db/dbRegionUtils.h index 4229e087b..6bddbb65e 100644 --- a/src/db/db/dbRegionUtils.h +++ b/src/db/db/dbRegionUtils.h @@ -527,15 +527,15 @@ private: /** * @brief A helper class for the region to text interaction functionality */ -template +template class DB_PUBLIC region_to_text_interaction_filter_base - : public db::box_scanner_receiver2 + : public db::box_scanner_receiver2 { public: region_to_text_interaction_filter_base (bool inverse); void preset (const OutputType *s); - void add (const db::Polygon *p, size_t, const db::Text *e, size_t); + void add (const db::Polygon *p, size_t, const TextType *e, size_t); void fill_output (); protected: @@ -549,13 +549,13 @@ private: /** * @brief A helper class for the region to text interaction functionality */ -template +template class DB_PUBLIC_TEMPLATE region_to_text_interaction_filter - : public region_to_text_interaction_filter_base + : public region_to_text_interaction_filter_base { public: region_to_text_interaction_filter (OutputContainer &output, bool inverse) - : region_to_text_interaction_filter_base (inverse), mp_output (&output) + : region_to_text_interaction_filter_base (inverse), mp_output (&output) { // .. nothing yet .. } diff --git a/src/db/db/dbShapeRepository.h b/src/db/db/dbShapeRepository.h index d95578df9..b6cd89660 100644 --- a/src/db/db/dbShapeRepository.h +++ b/src/db/db/dbShapeRepository.h @@ -176,6 +176,15 @@ public: return m_text_repository; } + /** + * @brief Return the repository by tag + */ + template + const db::repository &repository (db::object_tag tag) const + { + return const_cast *> (this)->repository (tag); + } + void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const { db::mem_stat (stat, purpose, cat, m_polygon_repository, no_self, parent); diff --git a/src/db/db/dbShapes.cc b/src/db/db/dbShapes.cc index 9f6799d08..aef79fa21 100644 --- a/src/db/db/dbShapes.cc +++ b/src/db/db/dbShapes.cc @@ -234,6 +234,20 @@ Shapes::swap (Shapes &d) m_layers.swap (d.m_layers); } +static +Shapes::shape_type safe_insert_text (Shapes &shapes, const Shapes::shape_type &shape, tl::func_delegate_base &pm) +{ + // for texts referring to a string repository we go the safe way and + // simply instantiate and re-insert the text: + Shapes::shape_type::text_type p; + shape.text (p); + if (! shape.has_prop_id ()) { + return shapes.insert (p); + } else { + return shapes.insert (db::object_with_properties (p, pm (shape.prop_id ()))); + } +} + Shapes::shape_type Shapes::do_insert (const Shapes::shape_type &shape, const Shapes::unit_trans_type & /*t*/, tl::func_delegate_base &pm) { @@ -352,19 +366,23 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Shapes::unit_trans_typ case shape_type::ShortBoxArray: return (insert_by_tag (shape_type::short_box_array_type::tag (), shape, pm)); case shape_type::Text: - case shape_type::TextRef: - case shape_type::TextPtrArrayMember: { - // because texts can refer to a string repository we go the safe way and - // simply instantiate and re-insert the text: - shape_type::text_type p; - shape.text (p); - if (! shape.has_prop_id ()) { - return insert (p); + if (shape.text ().string_ref () != 0) { + return safe_insert_text (*this, shape, pm); } else { - return insert (db::object_with_properties (p, pm (shape.prop_id ()))); + return (insert_by_tag (shape_type::text_type::tag (), shape, pm)); } } + case shape_type::TextRef: + { + if (shape.text_ref ().obj ().string_ref () != 0) { + return safe_insert_text (*this, shape, pm); + } else { + return (insert_by_tag (shape_type::text_ref_type::tag (), shape, pm)); + } + } + case shape_type::TextPtrArrayMember: + return safe_insert_text (*this, shape, pm); case shape_type::TextPtrArray: tl_assert (layout () != 0); // cannot translate the array members return insert_array_by_tag (shape_type::text_ptr_array_type::tag (), shape, shape_repository (), pm); diff --git a/src/db/db/dbText.h b/src/db/db/dbText.h index cbf4b83db..828518356 100644 --- a/src/db/db/dbText.h +++ b/src/db/db/dbText.h @@ -159,6 +159,9 @@ inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int class DB_PUBLIC StringRepository { public: + typedef std::set string_refs_type; + typedef string_refs_type::const_iterator iterator; + /** * @brief Constructor */ @@ -216,6 +219,22 @@ public: return m_string_refs.size (); } + /** + * @brief Iterates over the string refs (begin) + */ + iterator begin () const + { + return m_string_refs.begin (); + } + + /** + * @brief Iterates over the string refs (end) + */ + iterator end () const + { + return m_string_refs.end (); + } + void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const { if (! no_self) { @@ -559,6 +578,21 @@ public: } } + /** + * @brief Gets the StringRef object is there is one + * + * If the string is a plain text kept internally, this method returns 0. + */ + const StringRef *string_ref () const + { + size_t p = (size_t) mp_ptr; + if (p & 1) { + return reinterpret_cast (p - 1); + } else { + return 0; + } + } + /** * @brief The transformation write accessor */ diff --git a/src/db/db/dbTextsUtils.h b/src/db/db/dbTextsUtils.h index 4f72c23c9..d1a5926f3 100644 --- a/src/db/db/dbTextsUtils.h +++ b/src/db/db/dbTextsUtils.h @@ -153,7 +153,7 @@ private: }; /** - * @brief A helper class for the text to region interaction functionality which acts as an text receiver + * @brief A helper class for the text ref to region interaction functionality which acts as an text receiver * * Note: This special scanner uses pointers to two different objects: texts and polygons. * It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate @@ -161,9 +161,9 @@ private: * * There is a special box converter which is able to sort that out as well. */ -template +template class text_to_region_interaction_filter - : public db::box_scanner_receiver2 + : public db::box_scanner_receiver2 { public: text_to_region_interaction_filter (OutputContainer &output) @@ -172,6 +172,19 @@ public: // .. nothing yet .. } + void add (const db::TextRef *t, size_t, const db::Polygon *p, size_t) + { + const OutputType *tt = 0; + tl::select (tt, t, p); + + if (m_seen.find (tt) == m_seen.end ()) { + if (db::interact (*p, t->obj ().transformed (t->trans ()))) { + m_seen.insert (tt); + mp_output->insert (*tt); + } + } + } + void add (const db::Text *t, size_t, const db::Polygon *p, size_t) { const OutputType *tt = 0; diff --git a/src/db/unit_tests/dbHierNetworkProcessorTests.cc b/src/db/unit_tests/dbHierNetworkProcessorTests.cc index 7096e93e7..344101665 100644 --- a/src/db/unit_tests/dbHierNetworkProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetworkProcessorTests.cc @@ -369,21 +369,21 @@ TEST(20_LocalClustersBasic) db::local_clusters clusters; EXPECT_EQ (local_clusters_to_string (clusters, conn), ""); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0)"); // one more shape cell.shapes (0).insert (db::PolygonRef (poly.transformed (db::Trans (db::Vector (10, 20))), repo)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)"); // one more shape creating a new cluster cell.shapes (2).insert (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1100))), repo)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)\n" "#2:[2](0,1100;0,2100;1000,2100;1000,1100)" @@ -393,7 +393,7 @@ TEST(20_LocalClustersBasic) cell.shapes (2).insert (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1000))), repo)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20);[2](0,1000;0,2000;1000,2000;1000,1000);[2](0,1100;0,2100;1000,2100;1000,1100)" ); @@ -402,7 +402,7 @@ TEST(20_LocalClustersBasic) cell.shapes (1).insert (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1100))), repo)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20);[2](0,1000;0,2000;1000,2000;1000,1000);[2](0,1100;0,2100;1000,2100;1000,1100)\n" "#2:[1](0,1100;0,2100;1000,2100;1000,1100)" @@ -430,21 +430,21 @@ TEST(21_LocalClustersBasicWithAttributes) db::local_clusters clusters; EXPECT_EQ (local_clusters_to_string (clusters, conn), ""); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0)"); // one more shape cell.shapes (0).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (10, 20))), repo), 1)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1"); // one more shape creating a new cluster cell.shapes (2).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1100))), repo), 2)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1\n" "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2" @@ -454,7 +454,7 @@ TEST(21_LocalClustersBasicWithAttributes) cell.shapes (2).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1000))), repo), 3)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20);[2](0,1000;0,2000;1000,2000;1000,1000);[2](0,1100;0,2100;1000,2100;1000,1100)%1%2%3" ); @@ -463,7 +463,7 @@ TEST(21_LocalClustersBasicWithAttributes) cell.shapes (1).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1100))), repo), 4)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20);[2](0,1000;0,2000;1000,2000;1000,1000);[2](0,1100;0,2100;1000,2100;1000,1100)%1%2%3\n" "#2:[1](0,1100;0,2100;1000,2100;1000,1100)%4" @@ -491,21 +491,21 @@ TEST(22_LocalClustersWithGlobal) db::local_clusters clusters; EXPECT_EQ (local_clusters_to_string (clusters, conn), ""); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0)"); // one more shape cell.shapes (0).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (10, 20))), repo), 1)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1"); // one more shape creating a new cluster cell.shapes (2).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1100))), repo), 2)); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1\n" "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2" @@ -514,7 +514,7 @@ TEST(22_LocalClustersWithGlobal) conn.connect_global (0, "GLOBAL"); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1+GLOBAL\n" "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2" @@ -523,7 +523,7 @@ TEST(22_LocalClustersWithGlobal) conn.connect_global (2, "GLOBAL2"); clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1+GLOBAL\n" "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2+GLOBAL2" @@ -533,7 +533,7 @@ TEST(22_LocalClustersWithGlobal) // now, GLOBAL2 will connect these clusters clusters.clear (); - clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20);[2](0,1100;0,2100;1000,2100;1000,1100)%1%2+GLOBAL+GLOBAL2" ); @@ -570,7 +570,7 @@ TEST(23_LocalClustersWithEdges) conn.connect (0); db::local_clusters clusters; - clusters.build_clusters (cell, db::ShapeIterator::Edges, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,500);[0](0,500;0,1000)\n" "#2:[0](2000,500;1000,250);[0](1500,375;0,0)\n" @@ -585,7 +585,7 @@ TEST(23_LocalClustersWithEdges) conn.connect (0); db::local_clusters clusters; - clusters.build_clusters (cell, db::ShapeIterator::Edges, conn); + clusters.build_clusters (cell, conn); EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,500);[0](0,500;0,1000);[0](1500,375;0,0);[0](0,1000;2000,1000);[0](2000,1000;2000,500);[0](2000,500;1000,250)"); } } @@ -700,7 +700,7 @@ TEST(40_HierClustersBasic) db::Connectivity conn; conn.connect (l1, l1); - hc.build (ly, top, db::ShapeIterator::Polygons, conn); + hc.build (ly, top, conn); int n, nc; const db::connected_clusters *cluster; @@ -815,7 +815,7 @@ TEST(41_HierClustersRecursiveClusterShapeIterator) db::Connectivity conn; conn.connect (l1, l1); - hc.build (ly, top, db::ShapeIterator::Polygons, conn); + hc.build (ly, top, conn); std::string res; int n = 0; @@ -860,7 +860,7 @@ TEST(41_HierClustersRecursiveClusterIterator) db::Connectivity conn; conn.connect (l1, l1); - hc.build (ly, top, db::ShapeIterator::Polygons, conn); + hc.build (ly, top, conn); std::string res; int n = 0; @@ -1020,7 +1020,7 @@ static void run_hc_test (tl::TestBase *_this, const std::string &file, const std conn.connect_global (l6, "BULK2"); db::hier_clusters hc; - hc.build (ly, ly.cell (*ly.begin_top_down ()), db::ShapeIterator::Polygons, conn); + hc.build (ly, ly.cell (*ly.begin_top_down ()), conn); std::vector > net_layers; @@ -1153,7 +1153,7 @@ static void run_hc_test_with_backannotation (tl::TestBase *_this, const std::str conn.connect_global (l6, "BULK2"); db::hier_clusters hc; - hc.build (ly, ly.cell (*ly.begin_top_down ()), db::ShapeIterator::Polygons, conn); + hc.build (ly, ly.cell (*ly.begin_top_down ()), conn); std::map lm; lm[l1] = ly.insert_layer (db::LayerProperties (101, 0)); diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index f352bdb0c..060904eef 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -91,7 +91,7 @@ static void dump_recursive_nets_to_layout (const db::LayoutToNetlist &l2n, db::L bool any = false; for (std::map::const_iterator m = lmap.begin (); m != lmap.end () && !any; ++m) { - any = !db::recursive_cluster_shape_iterator (l2n.net_clusters (), l2n.layer_of (*m->first), c->cell_index (), n->cluster_id ()).at_end (); + any = !db::recursive_cluster_shape_iterator (l2n.net_clusters (), l2n.layer_of (*m->first), c->cell_index (), n->cluster_id ()).at_end (); } if (!any) { diff --git a/src/db/unit_tests/dbNetShapeTests.cc b/src/db/unit_tests/dbNetShapeTests.cc new file mode 100644 index 000000000..06e3a5432 --- /dev/null +++ b/src/db/unit_tests/dbNetShapeTests.cc @@ -0,0 +1,187 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbNetShape.h" +#include "dbShapes.h" +#include "tlUnitTest.h" + + +TEST(1) +{ + db::GenericRepository repo; + + db::NetShape s; + EXPECT_EQ (s.type () == db::NetShape::None, true); + EXPECT_EQ (s.bbox ().to_string (), "()"); + + db::Polygon p (db::Box (0, 0, 100, 200)); + s = db::NetShape (p, repo); + EXPECT_EQ (s.type () == db::NetShape::Polygon, true); + EXPECT_EQ (s.bbox ().to_string (), "(0,0;100,200)"); + EXPECT_EQ (s.polygon_ref ().obj ().to_string (), "(0,0;0,200;100,200;100,0)"); + EXPECT_EQ (db::NetShape (s.polygon_ref ()).type () == db::NetShape::Polygon, true); + EXPECT_EQ (db::NetShape (s.polygon_ref ()).polygon_ref ().obj ().to_string (), "(0,0;0,200;100,200;100,0)"); + + db::Text t ("abc", db::Trans (db::Vector (100, 200))); + s = db::NetShape (t, repo); + EXPECT_EQ (s.type () == db::NetShape::Text, true); + EXPECT_EQ (s.bbox ().to_string (), "(100,200;100,200)"); + EXPECT_EQ (s.text_ref ().obj ().to_string (), "('abc',r0 0,0)"); + EXPECT_EQ (db::NetShape (s.text_ref ()).type () == db::NetShape::Text, true); + EXPECT_EQ (db::NetShape (s.text_ref ()).text_ref ().obj ().to_string (), "('abc',r0 0,0)"); +} + +TEST(2) +{ + db::GenericRepository repo; + + db::NetShape s; + EXPECT_EQ (s.type () == db::NetShape::None, true); + EXPECT_EQ (s.bbox ().to_string (), "()"); + + db::Polygon p (db::Box (0, 0, 100, 200)); + s = db::NetShape (p, repo); + EXPECT_EQ (s.polygon_ref ().obj ().to_string (), "(0,0;0,200;100,200;100,0)"); + + s.transform (db::Disp (db::Vector (10, 20))); + EXPECT_EQ (s.bbox ().to_string (), "(10,20;110,220)"); + + db::Text t ("abc", db::Trans (db::Vector (100, 200))); + s = db::NetShape (t, repo); + EXPECT_EQ (s.text_ref ().obj ().to_string (), "('abc',r0 0,0)"); + + s.transform (db::Disp (db::Vector (10, 20))); + EXPECT_EQ (s.text_ref ().obj ().transformed (s.text_ref ().trans ()).to_string (), "('abc',r0 110,220)"); +} + +TEST(3) +{ + db::GenericRepository repo; + + db::NetShape s, s2; + EXPECT_EQ (s == db::NetShape (), true); + EXPECT_EQ (s != db::NetShape (), false); + EXPECT_EQ (s < db::NetShape (), false); + + db::Polygon p (db::Box (0, 0, 100, 200)); + s = db::NetShape (p, repo); + s2 = s; + EXPECT_EQ (s == db::NetShape (), false); + EXPECT_EQ (s != db::NetShape (), true); + EXPECT_EQ (s < db::NetShape (), false); + EXPECT_EQ (s == s2, true); + EXPECT_EQ (s != s2, false); + EXPECT_EQ (s < s2, false); + EXPECT_EQ (s2 < s, false); + s.transform (db::Disp (db::Vector (10, 20))); + EXPECT_EQ (s == s2, false); + EXPECT_EQ (s != s2, true); + EXPECT_EQ (s < s2, false); + EXPECT_EQ (s2 < s, true); + + db::Text t ("abc", db::Trans (db::Vector (100, 200))); + s = db::NetShape (t, repo); + EXPECT_EQ (s == s2, false); + EXPECT_EQ (s != s2, true); + EXPECT_EQ (s < s2, true); + EXPECT_EQ (s2 < s, false); + + s2 = s; + EXPECT_EQ (s == db::NetShape (), false); + EXPECT_EQ (s != db::NetShape (), true); + EXPECT_EQ (s < db::NetShape (), false); + EXPECT_EQ (s == s2, true); + EXPECT_EQ (s != s2, false); + EXPECT_EQ (s < s2, false); + EXPECT_EQ (s2 < s, false); + s.transform (db::Disp (db::Vector (10, 20))); + EXPECT_EQ (s == s2, false); + EXPECT_EQ (s != s2, true); + EXPECT_EQ (s < s2, false); + EXPECT_EQ (s2 < s, true); +} + +TEST(4) +{ + db::GenericRepository repo; + + db::NetShape s; + EXPECT_EQ (s.type () == db::NetShape::None, true); + EXPECT_EQ (s.bbox ().to_string (), "()"); + + db::Polygon p (db::Box (0, 0, 100, 200)); + s = db::NetShape (p, repo); + + db::Shapes shapes; + s.insert_into (shapes); + + db::Text t ("abc", db::Trans (db::Vector (100, 200))); + s = db::NetShape (t, repo); + s.insert_into (shapes); + + db::ShapeIterator si = shapes.begin (db::ShapeIterator::All); + EXPECT_EQ (si->to_string (), "polygon (0,0;0,200;100,200;100,0)"); + ++si; + EXPECT_NE (si.at_end (), true); + EXPECT_EQ (si->to_string (), "text ('abc',r0 100,200)"); + ++si; + EXPECT_EQ (si.at_end (), true); +} + +TEST(5) +{ + db::GenericRepository repo; + + db::NetShape sp1 (db::Polygon (db::Box (10, 20, 100, 200)), repo); + db::NetShape sp2 (db::Polygon (db::Box (80, 20, 180, 200)), repo); + db::NetShape sp3 (db::Polygon (db::Box (10, 320, 100, 500)), repo); + + db::NetShape st1 (db::Text ("abc", db::Trans (db::Vector (0, 0))), repo); + db::NetShape st2 (db::Text ("xyz", db::Trans (db::Vector (50, 60))), repo); + + EXPECT_EQ (sp1.interacts_with (db::NetShape ()), false); + EXPECT_EQ (sp1.interacts_with_transformed (db::NetShape (), db::Trans (db::Vector (1000, 0))), false); + EXPECT_EQ (sp1.interacts_with (sp1), true); + EXPECT_EQ (sp1.interacts_with_transformed (sp1, db::Trans (db::Vector (1000, 0))), false); + EXPECT_EQ (sp1.interacts_with (sp2), true); + EXPECT_EQ (sp2.interacts_with (sp1), true); + EXPECT_EQ (sp1.interacts_with (sp3), false); + EXPECT_EQ (sp1.interacts_with_transformed (sp3, db::Trans (db::Vector (50, -200))), true); + EXPECT_EQ (sp3.interacts_with (sp1), false); + EXPECT_EQ (sp3.interacts_with_transformed (sp1, db::Trans (db::Vector (50, 200))), true); + + EXPECT_EQ (sp1.interacts_with (st1), false); + EXPECT_EQ (sp1.interacts_with_transformed (st1, db::Trans (db::Vector (10, 20))), true); + EXPECT_EQ (sp1.interacts_with_transformed (st1, db::Trans (db::Vector (5, 20))), false); + EXPECT_EQ (sp1.interacts_with (st2), true); + + EXPECT_EQ (st1.interacts_with (sp1), false); + EXPECT_EQ (st1.interacts_with_transformed (sp1, db::Trans (db::Vector (-10, -20))), true); + EXPECT_EQ (st1.interacts_with_transformed (sp1, db::Trans (db::Vector (-5, -20))), false); + EXPECT_EQ (st2.interacts_with (sp1), true); + + EXPECT_EQ (st1.interacts_with (st1), true); + EXPECT_EQ (st1.interacts_with_transformed (st1, db::Trans (db::Vector (-5, -20))), false); + EXPECT_EQ (st2.interacts_with (st1), false); + EXPECT_EQ (st2.interacts_with_transformed (st1, db::Trans (db::Vector (50, 60))), true); +} diff --git a/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc b/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc index cf0c13caa..e26e5881d 100644 --- a/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc @@ -123,7 +123,7 @@ TEST(10_MOS3DeviceExtractorTest) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor ex ("MOS3"); @@ -179,7 +179,7 @@ TEST(11_MOS3DeviceExtractorTestNotRectangularGate) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor ex ("MOS3"); @@ -235,7 +235,7 @@ TEST(12_MOS3DeviceExtractorTestCircular) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor ex ("MOS3"); @@ -293,7 +293,7 @@ TEST(20_MOS4DeviceExtractorTest) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor ex ("MOS4"); @@ -354,7 +354,7 @@ TEST(21_MOS4DeviceExtractorTestNotRectangularGate) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor ex ("MOS4"); @@ -415,7 +415,7 @@ TEST(22_MOS4DeviceExtractorTestCircular) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor ex ("MOS4"); @@ -475,7 +475,7 @@ TEST(30_DMOS3DeviceExtractorTest) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor ex ("DMOS3", true); @@ -533,7 +533,7 @@ TEST(31_DMOS3DeviceExtractorTestNotRectangularGate) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor ex ("DMOS3", true); @@ -591,7 +591,7 @@ TEST(32_DMOS3DeviceExtractorTestCircular) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor ex ("DMOS3", true); @@ -651,7 +651,7 @@ TEST(40_DMOS4DeviceExtractorTest) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor ex ("DMOS4", true); @@ -714,7 +714,7 @@ TEST(41_DMOS4DeviceExtractorTestNotRectangularGate) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor ex ("DMOS4", true); @@ -777,7 +777,7 @@ TEST(42_DMOS4DeviceExtractorTestCircular) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor ex ("DMOS4", true); diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 8cff11d1e..fecf213be 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -59,7 +59,7 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la return lid; } -static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters &clusters, db::Layout &ly, const std::map &lmap, const db::CellMapping &cmap, bool with_device_cells = false) +static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters &clusters, db::Layout &ly, const std::map &lmap, const db::CellMapping &cmap, bool with_device_cells = false) { std::set device_cells_seen; @@ -69,7 +69,7 @@ static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters< for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { - const db::local_cluster &lc = clusters.clusters_per_cell (c->cell_index ()).cluster_by_id (n->cluster_id ()); + const db::local_cluster &lc = clusters.clusters_per_cell (c->cell_index ()).cluster_by_id (n->cluster_id ()); bool any_shapes = false; for (std::map::const_iterator m = lmap.begin (); m != lmap.end () && !any_shapes; ++m) { @@ -84,8 +84,8 @@ static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters< for (std::map::const_iterator m = lmap.begin (); m != lmap.end (); ++m) { db::Shapes &target = net_cell.shapes (m->second); - for (db::local_cluster::shape_iterator s = lc.begin (m->first); !s.at_end (); ++s) { - target.insert (*s); + for (db::local_cluster::shape_iterator s = lc.begin (m->first); !s.at_end (); ++s) { + s->insert_into (target); } } @@ -137,12 +137,12 @@ static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters< const std::vector &td = d->device_class ()->terminal_definitions (); for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { - const db::local_cluster &dc = clusters.clusters_per_cell (dci).cluster_by_id (d->device_abstract ()->cluster_id_for_terminal (t->id ())); + const db::local_cluster &dc = clusters.clusters_per_cell (dci).cluster_by_id (d->device_abstract ()->cluster_id_for_terminal (t->id ())); for (std::map::const_iterator m = lmap.begin (); m != lmap.end (); ++m) { db::Shapes &target = device_cell.shapes (m->second); - for (db::local_cluster::shape_iterator s = dc.begin (m->first); !s.at_end (); ++s) { - target.insert (*s); + for (db::local_cluster::shape_iterator s = dc.begin (m->first); !s.at_end (); ++s) { + s->insert_into (target); } } @@ -233,7 +233,7 @@ TEST(1_DeviceAndNetExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); @@ -452,7 +452,7 @@ TEST(2_DeviceAndNetExtractionFlat) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); @@ -686,7 +686,7 @@ TEST(3_DeviceAndNetExtractionWithImplicitConnections) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); @@ -935,7 +935,7 @@ TEST(4_ResAndCapExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); @@ -1182,7 +1182,7 @@ TEST(5_ResAndCapWithBulkExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS4Transistor nmos_ex ("NMOS"); @@ -1449,7 +1449,7 @@ TEST(6_BJT3TransistorExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS4Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS4Transistor nmos_ex ("NMOS"); @@ -1656,7 +1656,7 @@ TEST(7_DiodeExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorDiode diode_ex ("DIODE"); @@ -1790,7 +1790,7 @@ TEST(8_DiodeExtractionScaled) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorDiode diode_ex ("DIODE"); @@ -1951,7 +1951,7 @@ TEST(9_StrictDeviceExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS", true /*strict*/); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS", true /*strict*/); @@ -2184,7 +2184,7 @@ TEST(10_DeviceExtractionWithBreakoutCells) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); @@ -2352,7 +2352,7 @@ TEST(11_DeviceExtractionWithSameClass) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorResistor polyres_ex ("RES", 50.0); db::NetlistDeviceExtractorResistor diffres_ex ("RES", 150.0); @@ -2474,7 +2474,7 @@ TEST(12_FloatingSubcircuitExtraction) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); @@ -2628,7 +2628,7 @@ TEST(13_RemoveDummyPins) // perform the extraction db::Netlist nl; - db::hier_clusters cl; + db::hier_clusters cl; db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index 7962b945a..d2753f09a 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -75,7 +75,8 @@ SOURCES = \ dbBoxScannerTests.cc \ dbBoxTests.cc \ dbArrayTests.cc \ - dbDeepTextsTests.cc + dbDeepTextsTests.cc \ + dbNetShapeTests.cc INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC diff --git a/src/laybasic/laybasic/layNetInfoDialog.cc b/src/laybasic/laybasic/layNetInfoDialog.cc index f9ce3a2ea..9deaa7376 100644 --- a/src/laybasic/laybasic/layNetInfoDialog.cc +++ b/src/laybasic/laybasic/layNetInfoDialog.cc @@ -87,7 +87,7 @@ size_t count_shapes (db::LayoutToNetlist *l2ndb, db::Net *net, unsigned int laye size_t cluster_id = net->cluster_id (); size_t n = 0; - for (db::recursive_cluster_shape_iterator shapes (l2ndb->net_clusters (), layer, cell_index, cluster_id); ! shapes.at_end (); ++shapes) { + for (db::recursive_cluster_shape_iterator shapes (l2ndb->net_clusters (), layer, cell_index, cluster_id); ! shapes.at_end (); ++shapes) { ++n; } return n; @@ -278,7 +278,11 @@ void NetInfoDialog::update_info_text () std::string l = layer_string (mp_l2ndb.get (), *layer); - for (db::recursive_cluster_shape_iterator si (mp_l2ndb->net_clusters (), *layer, cell_index, cluster_id); ! si.at_end (); ++si) { + for (db::recursive_cluster_shape_iterator si (mp_l2ndb->net_clusters (), *layer, cell_index, cluster_id); ! si.at_end (); ++si) { + + if (si->type () != db::NetShape::Polygon) { + continue; + } if (tot_shapes++ >= max_shapes) { incomplete = true; @@ -295,7 +299,7 @@ void NetInfoDialog::update_info_text () statinfo_area.insert (std::make_pair (*layer, db::coord_traits::area_type (0))); } - s->second.push_back (si->instantiate ()); + s->second.push_back (si->polygon_ref ().instantiate ()); std::string c (ly->cell_name (si.cell_index ())); c += " (with "; diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index aee0bc4b1..3c0882ad0 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -987,9 +987,9 @@ NetlistBrowserPage::adjust_view () for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) { db::Box layer_bbox; - db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id); + db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id); while (! shapes.at_end ()) { - layer_bbox += shapes.trans () * shapes->box (); + layer_bbox += shapes->bbox (); ++shapes; } @@ -1187,15 +1187,19 @@ NetlistBrowserPage::produce_highlights_for_net (const db::Net *net, size_t &n_ma db::LayerProperties lp = layout->get_properties (*layer); std::map::const_iterator display = display_by_lp.find (lp); - db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id); + db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id); while (! shapes.at_end ()) { + if (shapes->type () != db::NetShape::Polygon) { + continue; + } + if (n_markers == m_max_shape_count) { return true; } mp_markers.push_back (new lay::Marker (mp_view, m_cv_index)); - mp_markers.back ()->set (*shapes, net_trans * shapes.trans (), tv); + mp_markers.back ()->set (shapes->polygon_ref (), net_trans * shapes.trans (), tv); if (net_color.isValid ()) {