From 8fb4e36809c495c948a9f338500ae8e29af2eda9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 17 Jan 2023 17:08:36 +0100 Subject: [PATCH] WIP: refactoring, preparing polygon-to-edge with properties --- src/db/db/dbAsIfFlatRegion.cc | 5 +- src/db/db/dbCell.cc | 10 +- src/db/db/dbCellMapping.cc | 2 +- src/db/db/dbClipboardData.cc | 14 +- src/db/db/dbDeepRegion.cc | 150 ++++++++++++++-------- src/db/db/dbFlatRegion.cc | 2 +- src/db/db/dbHierProcessor.cc | 117 +++++++++++++++++ src/db/db/dbHierarchyBuilder.cc | 16 +-- src/db/db/dbLayoutDiff.cc | 8 +- src/db/db/dbLayoutUtils.cc | 44 ++++--- src/db/db/dbLayoutUtils.h | 12 +- src/db/db/dbLibraryProxy.cc | 2 +- src/db/db/dbLocalOperation.cc | 37 ++---- src/db/db/dbLocalOperation.h | 8 +- src/db/db/dbLocalOperationUtils.cc | 27 ---- src/db/db/dbLocalOperationUtils.h | 130 ++++++++++++++++++- src/db/db/dbOriginalLayerRegion.cc | 2 +- src/db/db/gsiDeclDbCell.cc | 2 +- src/layui/layui/layLayoutViewFunctions.cc | 4 +- 19 files changed, 415 insertions(+), 177 deletions(-) diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 426212a24..939588633 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -266,10 +266,7 @@ void AsIfFlatRegion::invalidate_bbox () void AsIfFlatRegion::merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc, db::PropertiesRepository *target_rp) const { - db::PropertyMapper pm; - if (target_rp && properties_repository ()) { - pm = db::PropertyMapper (*target_rp, *properties_repository ()); - } + db::PropertyMapper pm (target_rp, properties_repository ()); db::EdgeProcessor ep (report_progress (), progress_desc ()); ep.set_base_verbosity (base_verbosity ()); diff --git a/src/db/db/dbCell.cc b/src/db/db/dbCell.cc index 1d991db4c..64efb2aaf 100644 --- a/src/db/db/dbCell.cc +++ b/src/db/db/dbCell.cc @@ -766,7 +766,7 @@ Cell::copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_ma } if (target_layout != source_layout) { - db::PropertyMapper pm (*target_layout, *source_layout); + db::PropertyMapper pm (target_layout, source_layout); db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm); @@ -915,7 +915,7 @@ Cell::move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping) } if (target_layout != source_layout) { - db::PropertyMapper pm (*target_layout, *source_layout); + db::PropertyMapper pm (target_layout, source_layout); db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm); @@ -988,7 +988,7 @@ Cell::move_tree (db::Cell &source_cell) throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); } - db::PropertyMapper pm (*target_layout, *source_layout); + db::PropertyMapper pm (target_layout, source_layout); db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); db::CellMapping cm; @@ -1022,7 +1022,7 @@ Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm) throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); } - db::PropertyMapper pm (*target_layout, *source_layout); + db::PropertyMapper pm (target_layout, source_layout); db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); db::LayerMapping lm; @@ -1049,7 +1049,7 @@ Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); } - db::PropertyMapper pm (*target_layout, *source_layout); + db::PropertyMapper pm (target_layout, source_layout); db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); std::vector source_cells; diff --git a/src/db/db/dbCellMapping.cc b/src/db/db/dbCellMapping.cc index 6959d78d3..c4255f762 100644 --- a/src/db/db/dbCellMapping.cc +++ b/src/db/db/dbCellMapping.cc @@ -371,7 +371,7 @@ CellMapping::do_create_missing_mapping (db::Layout &layout_a, const db::Layout & if (! new_cells.empty ()) { - db::PropertyMapper pm (layout_a, layout_b); + db::PropertyMapper pm (&layout_a, &layout_b); // Note: this avoids frequent cell index table rebuilds if source and target layout are identical layout_a.start_changes (); diff --git a/src/db/db/dbClipboardData.cc b/src/db/db/dbClipboardData.cc index 5add96e4b..36c515333 100644 --- a/src/db/db/dbClipboardData.cc +++ b/src/db/db/dbClipboardData.cc @@ -29,7 +29,7 @@ namespace db ClipboardData::ClipboardData () : m_layout (), m_incomplete_cells () { - m_prop_id_map.set_target (m_layout); + m_prop_id_map.set_target (&m_layout); m_container_cell_index = m_layout.add_cell (""); } @@ -47,7 +47,7 @@ ClipboardData::add (const db::Layout &layout, unsigned int layer, const db::Shap m_layout.insert_layer (layer, layout.get_properties (layer)); } - m_prop_id_map.set_source (layout); + m_prop_id_map.set_source (&layout); m_layout.cell (m_container_cell_index).shapes (layer).insert (shape, m_prop_id_map); } @@ -60,7 +60,7 @@ ClipboardData::add (const db::Layout &layout, unsigned int layer, const db::Shap m_layout.insert_layer (layer, layout.get_properties (layer)); } - m_prop_id_map.set_source (layout); + m_prop_id_map.set_source (&layout); db::Shape new_shape = m_layout.cell (m_container_cell_index).shapes (layer).insert (shape, m_prop_id_map); m_layout.cell (m_container_cell_index).shapes (layer).transform (new_shape, trans); } @@ -80,7 +80,7 @@ ClipboardData::add (const db::Layout &layout, const db::Instance &inst, unsigned } // Insert the instance mapping the cell to the target cell_index and the property ID using the map - m_prop_id_map.set_source (layout); + m_prop_id_map.set_source (&layout); tl::const_map im (target_cell_index); m_layout.cell (m_container_cell_index).insert (inst, im, m_prop_id_map); } @@ -102,7 +102,7 @@ ClipboardData::add (const db::Layout &layout, const db::Instance &inst, unsigned } // Insert the instance mapping the cell to the target cell_index and the property ID using the map - m_prop_id_map.set_source (layout); + m_prop_id_map.set_source (&layout); tl::const_map im (target_cell_index); db::Instance new_inst = m_layout.cell (m_container_cell_index).insert (inst, im, m_prop_id_map); m_layout.cell (m_container_cell_index).transform (new_inst, trans); @@ -123,7 +123,7 @@ ClipboardData::add (const db::Layout &layout, const db::Cell &cell, unsigned int m_context_info.erase (target_cell_index); } - m_prop_id_map.set_source (layout); + m_prop_id_map.set_source (&layout); // copy the shapes for (unsigned int l = 0; l < layout.layers (); ++l) { @@ -157,7 +157,7 @@ std::vector ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::Cell *cell, std::vector *new_tops, ClipboardDataInsertReceiver *insert_receiver) const { std::vector new_layers; - PropertyMapper prop_id_map (layout, m_layout); + PropertyMapper prop_id_map (&layout, &m_layout); std::map layer_map; for (unsigned int l = 0; l < layout.layers (); ++l) { diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 8b060070e..dafed0cea 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1285,12 +1285,41 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy) namespace { +template +static +std::map, std::vector > > +separate_by_same_properties (const shape_interactions, db::object_with_properties > &interactions, db::PropertyMapper &pms, db::PropertyMapper &pmi) +{ + std::map, std::vector > > by_prop_id; + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + + const db::object_with_properties &subject = interactions.subject_shape (i->first); + + std::pair, std::vector > &s2p = by_prop_id [pms (subject.properties_id ())]; + s2p.first.push_back (&subject); + + for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) { + + const std::pair > &intruder = interactions.intruder_shape (*ii); + + if (subject.properties_id () == pmi (intruder.second.properties_id ())) { + s2p.second.push_back (&intruder.second); + } + + } + + } + + return by_prop_id; +} + class PolygonToEdgeLocalOperation - : public local_operation + : public local_operation { public: - PolygonToEdgeLocalOperation () - : local_operation () + PolygonToEdgeLocalOperation (db::PropertiesRepository *target_pr, const db::PropertiesRepository *source_pr) + : local_operation (), m_pm (target_pr, source_pr) { // .. nothing yet .. } @@ -1299,63 +1328,75 @@ public: virtual bool requests_single_subjects () const { return true; } virtual std::string description () const { return std::string ("polygon to edges"); } - virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const { db::EdgeProcessor ep; ep.set_base_verbosity (50); - for (shape_interactions::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) { - ep.insert (s->second); - } + auto by_prop_id = separate_by_same_properties (interactions, m_pm, m_pm); + for (auto shapes_by_prop_id = by_prop_id.begin (); shapes_by_prop_id != by_prop_id.end (); ++shapes_by_prop_id) { - if (interactions.num_intruders () == 0) { + db::properties_id_type prop_id = shapes_by_prop_id->first; - db::EdgeToEdgeSetGenerator eg (results.front ()); - db::MergeOp op (0); - ep.process (eg, op); - - } else { - - // With intruders: to compute our local contribution we take the edges without and with intruders - // and deliver what is in both sets - - db::MergeOp op (0); - - std::vector edges1; - db::EdgeContainer ec1 (edges1); - ep.process (ec1, op); - - ep.clear (); - - for (shape_interactions::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) { - ep.insert (s->second); - } - for (shape_interactions::intruder_iterator i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) { - ep.insert (i->second.second); + for (auto s = shapes_by_prop_id->second.first.begin (); s != shapes_by_prop_id->second.first.end (); ++s) { + ep.insert (**s); } - std::vector edges2; - db::EdgeContainer ec2 (edges2); - ep.process (ec2, op); + db::property_injector > results_with_properties (&results.front (), prop_id); - // Runs the boolean AND between the result with and without intruders + if (shapes_by_prop_id->second.second.empty ()) { - db::box_scanner scanner; - scanner.reserve (edges1.size () + edges2.size ()); + db::edge_to_edge_set_generator > > eg (results_with_properties, prop_id); + db::MergeOp op (0); + ep.process (eg, op); + + } else { + + // With intruders: to compute our local contribution we take the edges without and with intruders + // and deliver what is in both sets + + db::MergeOp op (0); + + std::vector edges1; + db::EdgeContainer ec1 (edges1); + ep.process (ec1, op); + + ep.clear (); + + for (auto s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) { + ep.insert (s->second); + } + for (auto i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) { + ep.insert (i->second.second); + } + + std::vector edges2; + db::EdgeContainer ec2 (edges2); + ep.process (ec2, op); + + // Runs the boolean AND between the result with and without intruders + + db::box_scanner scanner; + scanner.reserve (edges1.size () + edges2.size ()); + + for (std::vector::const_iterator i = edges1.begin (); i != edges1.end (); ++i) { + scanner.insert (i.operator-> (), 0); + } + for (std::vector::const_iterator i = edges2.begin (); i != edges2.end (); ++i) { + scanner.insert (i.operator-> (), 1); + } + + EdgeBooleanClusterCollector > > cluster_collector (&results_with_properties, EdgeAnd); + scanner.process (cluster_collector, 1, db::box_convert ()); - for (std::vector::const_iterator i = edges1.begin (); i != edges1.end (); ++i) { - scanner.insert (i.operator-> (), 0); } - for (std::vector::const_iterator i = edges2.begin (); i != edges2.end (); ++i) { - scanner.insert (i.operator-> (), 1); - } - - EdgeBooleanClusterCollector > cluster_collector (&results.front (), EdgeAnd); - scanner.process (cluster_collector, 1, db::box_convert ()); } } + +private: + mutable db::PropertyMapper m_pm; }; } @@ -1363,8 +1404,10 @@ public: EdgesDelegate * DeepRegion::edges (const EdgeFilterBase *filter) const { + std::unique_ptr res (new db::DeepEdges (deep_layer ().derived ())); + if (empty ()) { - return new db::DeepEdges (deep_layer ().derived ()); + return res.release (); } if (! filter && merged_semantics () && ! merged_polygons_available ()) { @@ -1373,11 +1416,9 @@ DeepRegion::edges (const EdgeFilterBase *filter) const const db::DeepLayer &polygons = deep_layer (); - db::PolygonToEdgeLocalOperation op; + db::PolygonToEdgeLocalOperation op (res->properties_repository (), &polygons.layout ().properties_repository ()); - db::local_processor proc (const_cast (&polygons.layout ()), - const_cast (&polygons.initial_cell ()), - polygons.breakout_cells ()); + db::local_processor proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), polygons.breakout_cells ()); proc.set_description (progress_desc ()); proc.set_report_progress (report_progress ()); @@ -1387,15 +1428,12 @@ DeepRegion::edges (const EdgeFilterBase *filter) const // a boolean core makes somewhat better hierarchy proc.set_boolean_core (true); - std::unique_ptr res (new db::DeepEdges (polygons.derived ())); - proc.run (&op, polygons.layer (), foreign_idlayer (), res->deep_layer ().layer ()); - return res.release (); - } else { const db::DeepLayer &polygons = merged_deep_layer (); + db::PropertyMapper pm (res->properties_repository (), &polygons.layout ().properties_repository ()); std::unique_ptr vars; @@ -1412,7 +1450,6 @@ DeepRegion::edges (const EdgeFilterBase *filter) const db::Layout &layout = const_cast (polygons.layout ()); - std::unique_ptr res (new db::DeepEdges (polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { db::ICplxTrans tr; @@ -1432,7 +1469,7 @@ DeepRegion::edges (const EdgeFilterBase *filter) const for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) { if (! filter || filter->selected ((*e).transformed (tr))) { - st.insert (*e); + st.insert (db::EdgeWithProperties (*e, pm (si->prop_id ()))); } } @@ -1441,9 +1478,10 @@ DeepRegion::edges (const EdgeFilterBase *filter) const } res->set_is_merged (merged_semantics () || is_merged ()); - return res.release (); } + + return res.release (); } RegionDelegate * diff --git a/src/db/db/dbFlatRegion.cc b/src/db/db/dbFlatRegion.cc index e96324c79..ab4a72209 100644 --- a/src/db/db/dbFlatRegion.cc +++ b/src/db/db/dbFlatRegion.cc @@ -431,7 +431,7 @@ const db::PropertiesRepository *FlatRegion::properties_repository () const void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const { - db::PropertyMapper pm (layout->properties_repository (), *mp_properties_repository.get_const ()); + db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ()); layout->cell (into_cell).shapes (into_layer).insert (*mp_polygons, pm); } diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 7a55bbecf..797ab0dee 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -542,6 +542,62 @@ subtract (std::unordered_set &res, const std::unordered_set +static void +subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout *layout, const db::local_processor *proc) +{ + if (other.empty ()) { + return; + } + + if (! proc->boolean_core ()) { + subtract_set (res, other); + return; + } + + size_t max_vertex_count = proc->max_vertex_count (); + double area_ratio = proc->area_ratio (); + + std::unordered_set first; + first.swap (res); + + std::map, std::vector > > by_prop_id; + for (auto i = first.begin (); i != first.end (); ++i) { + by_prop_id [i->properties_id ()].first.push_back (i.operator-> ()); + } + for (auto i = other.begin (); i != other.end (); ++i) { + by_prop_id [i->properties_id ()].second.push_back (i.operator-> ()); + } + + db::EdgeProcessor ep; + ep.set_base_verbosity (proc->base_verbosity () + 30); + + for (auto s2p = by_prop_id.begin (); s2p != by_prop_id.end (); ++s2p) { + + db::properties_id_type prop_id = s2p->first; + size_t p1 = 0, p2 = 1; + + ep.clear (); + + for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) { + ep.insert (**i, p1); + p1 += 2; + } + + for (auto i = s2p->second.second.begin (); i != s2p->second.second.end (); ++i) { + ep.insert (**i, p2); + p2 += 2; + } + + db::BooleanOp op (db::BooleanOp::ANotB); + db::polygon_ref_generator_with_properties pr (layout, res, prop_id); + db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count); + db::PolygonGenerator pg (splitter, true, true); + ep.process (pg, op); + + } +} + template static void subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout * /*layout*/, const db::local_processor *proc) @@ -572,6 +628,59 @@ subtract (std::unordered_set &res, const std::unordered_set res.swap (result); } +template +static void +subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout * /*layout*/, const db::local_processor *proc) +{ + if (other.empty ()) { + return; + } + + if (! proc->boolean_core ()) { + subtract_set (res, other); + return; + } + + std::unordered_set first; + first.swap (res); + + std::map, std::vector > > by_prop_id; + for (auto i = first.begin (); i != first.end (); ++i) { + by_prop_id [i->properties_id ()].first.push_back (i.operator-> ()); + } + for (auto i = other.begin (); i != other.end (); ++i) { + by_prop_id [i->properties_id ()].second.push_back (i.operator-> ()); + } + + for (auto s2p = by_prop_id.begin (); s2p != by_prop_id.end (); ++s2p) { + + if (s2p->second.second.empty ()) { + + for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) { + res.insert (**i); + } + + } else { + + db::box_scanner scanner; + scanner.reserve (s2p->second.first.size () + s2p->second.second.size ()); + + for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) { + scanner.insert (*i, 0); + } + for (auto i = s2p->second.second.begin (); i != s2p->second.second.end (); ++i) { + scanner.insert (*i, 1); + } + + db::property_injector > prop_inject (&res, s2p->first); + EdgeBooleanClusterCollector > > cluster_collector (&prop_inject, EdgeNot); + scanner.process (cluster_collector, 1, db::box_convert ()); + + } + + } +} + template static void subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout * /*layout*/, const db::local_processor * /*proc*/) @@ -761,7 +870,9 @@ template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; @@ -1340,7 +1451,9 @@ template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; @@ -1403,8 +1516,10 @@ template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; @@ -2421,7 +2536,9 @@ 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 acd25413c..8f03feb18 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -643,8 +643,8 @@ PolygonReferenceHierarchyBuilderShapeReceiver::PolygonReferenceHierarchyBuilderS } if (source_layout && source_layout != layout) { - m_pm.set_source (*source_layout); - m_pm.set_target (*layout); + m_pm.set_source (source_layout); + m_pm.set_target (layout); } } @@ -727,8 +727,8 @@ EdgeBuildingHierarchyBuilderShapeReceiver::EdgeBuildingHierarchyBuilderShapeRece : m_as_edges (as_edges) { if (source_layout && source_layout != layout) { - m_pm.set_source (*source_layout); - m_pm.set_target (*layout); + m_pm.set_source (source_layout); + m_pm.set_target (layout); } } @@ -787,8 +787,8 @@ void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, d EdgePairBuildingHierarchyBuilderShapeReceiver::EdgePairBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout) { if (source_layout && source_layout != layout) { - m_pm.set_source (*source_layout); - m_pm.set_target (*layout); + m_pm.set_source (source_layout); + m_pm.set_target (layout); } } @@ -810,8 +810,8 @@ TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeRece : mp_layout (layout) { if (source_layout && source_layout != layout) { - m_pm.set_source (*source_layout); - m_pm.set_target (*layout); + m_pm.set_source (source_layout); + m_pm.set_target (layout); } } diff --git a/src/db/db/dbLayoutDiff.cc b/src/db/db/dbLayoutDiff.cc index 3b35358a4..d52ec900e 100644 --- a/src/db/db/dbLayoutDiff.cc +++ b/src/db/db/dbLayoutDiff.cc @@ -670,11 +670,11 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout na.properties_repository () = a.properties_repository (); nb.properties_repository () = b.properties_repository (); - db::PropertyMapper prop_normalize_a (n, a); - db::PropertyMapper prop_normalize_b (n, b); + db::PropertyMapper prop_normalize_a (&n, &a); + db::PropertyMapper prop_normalize_b (&n, &b); - db::PropertyMapper prop_remap_to_a (na, n); - db::PropertyMapper prop_remap_to_b (nb, n); + db::PropertyMapper prop_remap_to_a (&na, &n); + db::PropertyMapper prop_remap_to_b (&nb, &n); // compare layers diff --git a/src/db/db/dbLayoutUtils.cc b/src/db/db/dbLayoutUtils.cc index a5f4d8ee7..b22464d51 100644 --- a/src/db/db/dbLayoutUtils.cc +++ b/src/db/db/dbLayoutUtils.cc @@ -26,6 +26,7 @@ #include "dbPolygonTools.h" #include "tlProgress.h" #include "tlTimer.h" +#include "tlThreads.h" namespace db { @@ -60,14 +61,14 @@ DirectLayerMapping::map_layer (const LayerProperties &lprops) // ------------------------------------------------------------------------------------ // PropertyMapper implementation -PropertyMapper::PropertyMapper (db::Layout &target, const db::Layout &source) - : mp_target (&target.properties_repository ()), mp_source (&source.properties_repository ()) +PropertyMapper::PropertyMapper (db::Layout *target, const db::Layout *source) + : mp_target (target ? &target->properties_repository () : 0), mp_source (source ? &source->properties_repository () : 0) { // .. nothing yet .. } -PropertyMapper::PropertyMapper (db::PropertiesRepository &target, const db::PropertiesRepository &source) - : mp_target (&target), mp_source (&source) +PropertyMapper::PropertyMapper (db::PropertiesRepository *target, const db::PropertiesRepository *source) + : mp_target (target), mp_source (source) { // .. nothing yet .. } @@ -88,11 +89,12 @@ PropertyMapper::PropertyMapper () * @brief Specify the source layout */ void -PropertyMapper::set_source (const db::Layout &source) +PropertyMapper::set_source (const db::Layout *source) { - if (&source.properties_repository () != mp_source) { + const db::PropertiesRepository *pr = source ? &source->properties_repository () : 0; + if (pr != mp_source) { m_prop_id_map.clear (); - mp_source = &source.properties_repository (); + mp_source = pr; } } @@ -100,11 +102,11 @@ PropertyMapper::set_source (const db::Layout &source) * @brief Specify the source property repository */ void -PropertyMapper::set_source (const db::PropertiesRepository &source) +PropertyMapper::set_source (const db::PropertiesRepository *source) { - if (&source != mp_source) { + if (source != mp_source) { m_prop_id_map.clear (); - mp_source = &source; + mp_source = source; } } @@ -112,11 +114,12 @@ PropertyMapper::set_source (const db::PropertiesRepository &source) * @brief Specify the target layout */ void -PropertyMapper::set_target (db::Layout &target) +PropertyMapper::set_target (db::Layout *target) { - if (&target.properties_repository () != mp_target) { + db::PropertiesRepository *pr = target ? &target->properties_repository () : 0; + if (pr != mp_target) { m_prop_id_map.clear (); - mp_target = &target.properties_repository (); + mp_target = pr; } } @@ -124,11 +127,11 @@ PropertyMapper::set_target (db::Layout &target) * @brief Specify the target property repository */ void -PropertyMapper::set_target (db::PropertiesRepository &target) +PropertyMapper::set_target (db::PropertiesRepository *target) { - if (&target != mp_target) { + if (target != mp_target) { m_prop_id_map.clear (); - mp_target = ⌖ + mp_target = target; } } @@ -138,13 +141,16 @@ PropertyMapper::set_target (db::PropertiesRepository &target) db::Layout::properties_id_type PropertyMapper::operator() (db::Layout::properties_id_type source_id) { - if (source_id == 0 || mp_source == mp_target) { + if (source_id == 0 || mp_source == mp_target || ! mp_source || ! mp_target) { return source_id; } tl_assert (mp_source != 0); tl_assert (mp_target != 0); + static tl::Mutex s_mutex; + tl::MutexLocker locker (&s_mutex); + std::map ::const_iterator p = m_prop_id_map.find (source_id); if (p == m_prop_id_map.end ()) { @@ -226,7 +232,7 @@ merge_layouts (db::Layout &target, } // provide the property mapper - db::PropertyMapper pm (target, source); + db::PropertyMapper pm (&target, &source); tl::RelativeProgress progress (tl::to_string (tr ("Merge cells")), all_cells_to_copy.size (), 1); @@ -338,7 +344,7 @@ copy_or_move_shapes (db::Layout &target, collect_cells_to_copy (source, source_cells, cell_mapping, all_top_level_cells, all_cells_to_copy); // provide the property mapper - db::PropertyMapper pm (target, source); + db::PropertyMapper pm (&target, &source); tl::RelativeProgress progress (tl::to_string (tr ("Merge cells")), all_cells_to_copy.size () * layer_mapping.size (), 1); diff --git a/src/db/db/dbLayoutUtils.h b/src/db/db/dbLayoutUtils.h index 4195dfa2e..fed5457c3 100644 --- a/src/db/db/dbLayoutUtils.h +++ b/src/db/db/dbLayoutUtils.h @@ -80,7 +80,7 @@ public: * @param source The source layout * @param target The target layout */ - PropertyMapper (db::Layout &target, const db::Layout &source); + PropertyMapper (db::Layout *target, const db::Layout *source); /** * @brief Instantiate a property mapper for mapping of property ids from the source to the target property repository @@ -88,7 +88,7 @@ public: * @param source The source property repository * @param target The target property repository */ - PropertyMapper (db::PropertiesRepository &target, const db::PropertiesRepository &source); + PropertyMapper (db::PropertiesRepository *target, const db::PropertiesRepository *source); /** * @brief Instantiate a property mapper for mapping of property ids from the source to the target layout @@ -101,22 +101,22 @@ public: /** * @brief Specify the source layout */ - void set_source (const db::Layout &source); + void set_source (const db::Layout *source); /** * @brief Specify the source property repository */ - void set_source (const db::PropertiesRepository &source); + void set_source (const db::PropertiesRepository *source); /** * @brief Specify the target layout */ - void set_target (db::Layout &target); + void set_target (db::Layout *target); /** * @brief Specify the target property repository */ - void set_target (db::PropertiesRepository &target); + void set_target (db::PropertiesRepository *target); /** * @brief The actual mapping function diff --git a/src/db/db/dbLibraryProxy.cc b/src/db/db/dbLibraryProxy.cc index 950bfd703..7afa8ce24 100644 --- a/src/db/db/dbLibraryProxy.cc +++ b/src/db/db/dbLibraryProxy.cc @@ -224,7 +224,7 @@ LibraryProxy::update (db::ImportLayerMapping *layer_mapping) clear_shapes (); clear_insts (); - PropertyMapper prop_id_map (*layout (), lib->layout ()); + PropertyMapper prop_id_map (layout (), &lib->layout ()); for (unsigned int l = 0; l < lib->layout ().layers (); ++l) { if (layer_indices [l] >= 0) { diff --git a/src/db/db/dbLocalOperation.cc b/src/db/db/dbLocalOperation.cc index 3797d2b35..b95ebea92 100644 --- a/src/db/db/dbLocalOperation.cc +++ b/src/db/db/dbLocalOperation.cc @@ -95,7 +95,9 @@ template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; @@ -203,7 +205,7 @@ template class DB_PUBLIC bool_and_or_not_local_operation bool_and_or_not_local_operation_with_properties::bool_and_or_not_local_operation_with_properties (bool is_and, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint) - : m_is_and (is_and), m_property_constraint (property_constraint), mp_target_pr (target_pr), mp_subject_pr (subject_pr), mp_intruder_pr (intruder_pr) + : m_is_and (is_and), m_property_constraint (property_constraint), m_pms (target_pr, subject_pr), m_pmi (target_pr, intruder_pr) { // .. nothing yet .. } @@ -226,9 +228,6 @@ template void bool_and_or_not_local_operation_with_properties::do_compute_local (db::Layout *layout, const shape_interactions, db::object_with_properties > &interactions, std::vector > > &results, size_t max_vertex_count, double area_ratio) const { - db::PropertyMapper pms (*mp_target_pr, *mp_subject_pr); - db::PropertyMapper pmi (*mp_target_pr, *mp_intruder_pr); - tl_assert (results.size () == 1); std::unordered_set > &result = results.front (); @@ -243,19 +242,19 @@ bool_and_or_not_local_operation_with_properties::do_compute_local (d if (i->second.empty ()) { if (! m_is_and) { - result.insert (db::object_with_properties (subject, pms (subject.properties_id ()))); + result.insert (db::object_with_properties (subject, m_pms (subject.properties_id ()))); } } else { - db::properties_id_type prop_id_s = pms (subject.properties_id ()); + db::properties_id_type prop_id_s = m_pms (subject.properties_id ()); auto &shapes_by_prop = by_prop_id [prop_id_s]; shapes_by_prop.first.push_front (subject); for (auto j = i->second.begin (); j != i->second.end (); ++j) { const db::object_with_properties &intruder = interactions.intruder_shape (*j).second; - db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : prop_id_s); + db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? m_pmi (intruder.properties_id ()) : prop_id_s); if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) { shapes_by_prop.second.insert (intruder); } @@ -303,19 +302,13 @@ bool_and_or_not_local_operation_with_properties::do_compute_local (d p2 += 2; } - std::unordered_set result_wo_props; - db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB); - db::polygon_ref_generator pr (layout, result_wo_props); + db::polygon_ref_generator_with_properties > pr (layout, result, prop_id); db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count); db::PolygonGenerator pg (splitter, true, true); ep.set_base_verbosity (50); ep.process (pg, op); - for (auto r = result_wo_props.begin (); r != result_wo_props.end (); ++r) { - result.insert (db::object_with_properties (*r, prop_id)); - } - } } @@ -416,7 +409,7 @@ template class DB_PUBLIC two_bool_and_not_local_operation two_bool_and_not_local_operation_with_properties::two_bool_and_not_local_operation_with_properties (db::PropertiesRepository *target1_pr, db::PropertiesRepository *target2_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint) : db::local_operation, db::object_with_properties, db::object_with_properties > (), - m_property_constraint (property_constraint), mp_target1_pr (target1_pr), mp_target2_pr (target2_pr), mp_subject_pr (subject_pr), mp_intruder_pr (intruder_pr) + m_property_constraint (property_constraint), m_pms (target1_pr, subject_pr), m_pmi (target1_pr, intruder_pr), m_pm12 (target2_pr, target1_pr) { // .. nothing yet .. } @@ -425,10 +418,6 @@ template void two_bool_and_not_local_operation_with_properties::do_compute_local (db::Layout *layout, const shape_interactions, db::object_with_properties > &interactions, std::vector > > &results, size_t max_vertex_count, double area_ratio) const { - db::PropertyMapper pms (*mp_target1_pr, *mp_subject_pr); - db::PropertyMapper pmi (*mp_target1_pr, *mp_intruder_pr); - db::PropertyMapper pm12 (*mp_target2_pr, *mp_target1_pr); - tl_assert (results.size () == 2); std::unordered_set > &result0 = results [0]; std::unordered_set > &result1 = results [1]; @@ -443,18 +432,18 @@ two_bool_and_not_local_operation_with_properties::do_compute_local ( if (i->second.empty ()) { - result1.insert (db::object_with_properties (subject, pms (subject.properties_id ()))); + result1.insert (db::object_with_properties (subject, m_pms (subject.properties_id ()))); } else { - db::properties_id_type prop_id_s = pms (subject.properties_id ()); + db::properties_id_type prop_id_s = m_pms (subject.properties_id ()); auto &shapes_by_prop = by_prop_id [prop_id_s]; shapes_by_prop.first.push_front (subject); for (auto j = i->second.begin (); j != i->second.end (); ++j) { const db::object_with_properties &intruder = interactions.intruder_shape (*j).second; - db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : prop_id_s); + db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? m_pmi (intruder.properties_id ()) : prop_id_s); if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) { shapes_by_prop.second.insert (intruder); } @@ -479,7 +468,7 @@ two_bool_and_not_local_operation_with_properties::do_compute_local ( result0.insert (db::object_with_properties (subject, prop_id)); } else if (others.empty ()) { // shortcut (not: keep, and: drop) - result1.insert (db::object_with_properties (subject, pm12 (prop_id))); + result1.insert (db::object_with_properties (subject, m_pm12 (prop_id))); } else { for (auto e = subject.begin_edge (); ! e.at_end(); ++e) { ep.insert (*e, p1); @@ -522,7 +511,7 @@ two_bool_and_not_local_operation_with_properties::do_compute_local ( result0.insert (db::object_with_properties (*r, prop_id)); } for (auto r = result1_wo_props.begin (); r != result1_wo_props.end (); ++r) { - result1.insert (db::object_with_properties (*r, pm12 (prop_id))); + result1.insert (db::object_with_properties (*r, m_pm12 (prop_id))); } } diff --git a/src/db/db/dbLocalOperation.h b/src/db/db/dbLocalOperation.h index 0323d06e5..93b12d9ff 100644 --- a/src/db/db/dbLocalOperation.h +++ b/src/db/db/dbLocalOperation.h @@ -31,6 +31,7 @@ #include "dbEdgeBoolean.h" #include "dbEdgeProcessor.h" #include "dbPropertyConstraint.h" +#include "dbLayoutUtils.h" #include #include @@ -168,8 +169,8 @@ public: private: bool m_is_and; db::PropertyConstraint m_property_constraint; - db::PropertiesRepository *mp_target_pr; - const db::PropertiesRepository *mp_subject_pr, *mp_intruder_pr; + mutable db::PropertyMapper m_pms; + mutable db::PropertyMapper m_pmi; }; typedef bool_and_or_not_local_operation_with_properties BoolAndOrNotLocalOperationWithProperties; @@ -212,8 +213,7 @@ public: private: db::PropertyConstraint m_property_constraint; - db::PropertiesRepository *mp_target1_pr, *mp_target2_pr; - const db::PropertiesRepository *mp_subject_pr, *mp_intruder_pr; + mutable db::PropertyMapper m_pms, m_pmi, m_pm12; }; typedef two_bool_and_not_local_operation_with_properties TwoBoolAndNotLocalOperationWithProperties; diff --git a/src/db/db/dbLocalOperationUtils.cc b/src/db/db/dbLocalOperationUtils.cc index 2ad889cc8..e280eabee 100644 --- a/src/db/db/dbLocalOperationUtils.cc +++ b/src/db/db/dbLocalOperationUtils.cc @@ -27,33 +27,6 @@ namespace db { -// ----------------------------------------------------------------------------------------------- -// class EdgeToEdgeSetGenerator - -EdgeToEdgeSetGenerator::EdgeToEdgeSetGenerator (std::unordered_set &edges, int tag, EdgeToEdgeSetGenerator *chained) - : mp_edges (&edges), m_tag (tag), mp_chained (chained) -{ - // .. nothing yet .. -} - -void EdgeToEdgeSetGenerator::put (const db::Edge &edge) -{ - mp_edges->insert (edge); - if (mp_chained) { - mp_chained->put (edge); - } -} - -void EdgeToEdgeSetGenerator::put (const db::Edge &edge, int tag) -{ - if (m_tag == 0 || m_tag == tag) { - mp_edges->insert (edge); - } - if (mp_chained) { - mp_chained->put (edge, tag); - } -} - // ----------------------------------------------------------------------------------------------- // class PolygonRefGenerator diff --git a/src/db/db/dbLocalOperationUtils.h b/src/db/db/dbLocalOperationUtils.h index 0000ca0d9..42484a243 100644 --- a/src/db/db/dbLocalOperationUtils.h +++ b/src/db/db/dbLocalOperationUtils.h @@ -123,31 +123,117 @@ private: typedef polygon_ref_generator PolygonRefGenerator; -class DB_PUBLIC EdgeToEdgeSetGenerator +template +class DB_PUBLIC polygon_ref_generator_with_properties; + +template <> +class DB_PUBLIC polygon_ref_generator_with_properties + : public PolygonSink +{ +public: + /** + * @brief Constructor + */ + polygon_ref_generator_with_properties (db::Layout *layout, std::unordered_set &polyrefs, db::properties_id_type prop_id) + : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs), m_prop_id (prop_id) + { + // .. nothing yet .. + } + + /** + * @brief Implementation of the PolygonSink interface + */ + void put (const db::Polygon &polygon) + { + tl::MutexLocker locker (&mp_layout->lock ()); + mp_polyrefs->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id)); + } + +private: + db::Layout *mp_layout; + std::unordered_set *mp_polyrefs; + db::properties_id_type m_prop_id; +}; + +template <> +class DB_PUBLIC polygon_ref_generator_with_properties + : public PolygonSink +{ +public: + /** + * @brief Constructor + */ + polygon_ref_generator_with_properties (db::Layout *, std::unordered_set &polygons, db::properties_id_type prop_id) + : mp_polygons (&polygons), m_prop_id (prop_id) + { + // .. nothing yet .. + } + + /** + * @brief Implementation of the PolygonSink interface + */ + virtual void put (const db::Polygon &polygon) + { + mp_polygons->insert (db::PolygonWithProperties (polygon, m_prop_id)); + } + +private: + std::unordered_set *mp_polygons; + db::properties_id_type m_prop_id; +}; + +typedef polygon_ref_generator PolygonRefGenerator; + +template +class DB_PUBLIC edge_to_edge_set_generator : public EdgeSink { public: /** * @brief Constructor */ - EdgeToEdgeSetGenerator (std::unordered_set &edges, int tag = 0, EdgeToEdgeSetGenerator *chained = 0); + edge_to_edge_set_generator (Container &edges, int tag = 0, EdgeSink *chained = 0) + : mp_edges (&edges), m_tag (tag), mp_chained (chained) + { + // .. nothing yet .. + } /** * @brief Implementation of the PolygonSink interface */ - virtual void put (const db::Edge &edge); + virtual void put (const db::Edge &edge) + { + if (mp_edges) { + mp_edges->insert (edge); + } + if (mp_chained) { + mp_chained->put (edge); + } + } /** * @brief Implementation of the PolygonSink interface */ - virtual void put (const db::Edge &edge, int tag); + virtual void put (const db::Edge &edge, int tag) + { + if (m_tag == 0 || m_tag == tag) { + if (mp_edges) { + mp_edges->insert (edge); + } + } + if (mp_chained) { + mp_chained->put (edge, tag); + } + } private: - std::unordered_set *mp_edges; + Container *mp_edges; int m_tag; - EdgeToEdgeSetGenerator *mp_chained; + EdgeSink *mp_chained; }; +typedef edge_to_edge_set_generator > EdgeToEdgeSetGenerator; + class DB_PUBLIC PolygonRefToShapesGenerator : public PolygonSink { @@ -185,6 +271,38 @@ private: size_t m_max_vertex_count; }; +template +class DB_PUBLIC property_injector +{ +public: + typedef typename Container::const_iterator const_iterator; + + property_injector (Container *container, db::properties_id_type prop_id) + : mp_container (container), m_prop_id (prop_id) + { + // .. nothing yet .. + } + + const_iterator begin () const + { + return mp_container->begin (); + } + + const_iterator end () const + { + return mp_container->end (); + } + + void insert (const T &t) + { + mp_container->insert (db::object_with_properties (t, m_prop_id)); + } + +private: + Container *mp_container; + db::properties_id_type m_prop_id; +}; + } #endif diff --git a/src/db/db/dbOriginalLayerRegion.cc b/src/db/db/dbOriginalLayerRegion.cc index d87da0dca..7b7f73dfb 100644 --- a/src/db/db/dbOriginalLayerRegion.cc +++ b/src/db/db/dbOriginalLayerRegion.cc @@ -423,7 +423,7 @@ OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell, db::PropertyMapper pm; if (m_iter.layout ()) { - pm = db::PropertyMapper (*layout, *m_iter.layout ()); + pm = db::PropertyMapper (layout, m_iter.layout ()); } // NOTE: if the source (r) is from the same layout than the shapes live in, we better diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index f3ce30aca..00db50666 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1192,7 +1192,7 @@ static void move_or_copy_from_other_cell (db::Cell *cell, db::Cell *src_cell, un } else if (cell->layout () != src_cell->layout ()) { - db::PropertyMapper pm (*cell->layout (), *src_cell->layout ()); + db::PropertyMapper pm (cell->layout (), src_cell->layout ()); db::ICplxTrans tr (src_cell->layout ()->dbu () / cell->layout ()->dbu ()); cell->shapes (dest_layer).insert_transformed (src_cell->shapes (src_layer), tr, pm); diff --git a/src/layui/layui/layLayoutViewFunctions.cc b/src/layui/layui/layLayoutViewFunctions.cc index 23e8cdf7d..b29cdc693 100644 --- a/src/layui/layui/layLayoutViewFunctions.cc +++ b/src/layui/layui/layLayoutViewFunctions.cc @@ -1646,7 +1646,7 @@ LayoutViewFunctions::cm_copy_layer () if (! same_layout) { // flat mode (different layouts) - db::PropertyMapper pm (view ()->cellview (m_copy_cvr)->layout (), view ()->cellview (m_copy_cva)->layout ()); + db::PropertyMapper pm (&view ()->cellview (m_copy_cvr)->layout (), &view ()->cellview (m_copy_cva)->layout ()); for (db::RecursiveShapeIterator si (view ()->cellview (m_copy_cva)->layout (), *view ()->cellview (m_copy_cva).cell (), m_copy_layera); ! si.at_end (); ++si) { target_cell.shapes (m_copy_layerr).insert (*si, si.trans (), pm); } @@ -1693,7 +1693,7 @@ LayoutViewFunctions::cm_copy_layer () } else if (! same_layout) { // current cell only mode (different layouts) - db::PropertyMapper pm (view ()->cellview (m_copy_cvr)->layout (), view ()->cellview (m_copy_cva)->layout ()); + db::PropertyMapper pm (&view ()->cellview (m_copy_cvr)->layout (), &view ()->cellview (m_copy_cva)->layout ()); for (db::Shapes::shape_iterator si = view ()->cellview (m_copy_cva).cell ()->shapes (m_copy_layera).begin (db::ShapeIterator::All); ! si.at_end (); ++si) { target_cell.shapes (m_copy_layerr).insert (*si, pm); }