diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h index d9cbf840f..7c13a67e0 100644 --- a/src/db/db/dbCompoundOperation.h +++ b/src/db/db/dbCompoundOperation.h @@ -1755,8 +1755,10 @@ public: : mp_node (node) { } - const TransformationReducer *vars () const { return mp_node->vars (); } - bool wants_variants () const { return mp_node->wants_variants (); } + virtual const TransformationReducer *vars () const + { + return mp_node->vars (); + } protected: virtual void do_compute_local (db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const @@ -1802,8 +1804,10 @@ public: } } - const TransformationReducer *vars () const { return mp_node->vars (); } - bool wants_variants () const { return mp_node->wants_variants (); } + virtual const TransformationReducer *vars () const + { + return mp_node->vars (); + } protected: virtual void do_compute_local (db::Layout *layout, db::Cell *cell, const shape_interactions, db::object_with_properties > &interactions, std::vector > > &results, const db::LocalProcessorBase *proc) const diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index ae584c443..6c1438a22 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -2012,9 +2012,15 @@ public: return tl::to_string (tr ("Generic DRC check")); } + virtual const db::TransformationReducer *vars () const + { + return &m_vars; + } + private: EdgeRelationFilter m_check; bool m_has_other; + db::MagnificationReducer m_vars; }; } @@ -2032,28 +2038,6 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord const db::DeepLayer &edges = merged_deep_layer (); - // create cell variants for magnification if needed - - db::cell_variants_collector vars; - vars.collect (edges.layout (), edges.initial_cell ()); - - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (edges).separate_variants (vars); - - if (other_deep && &other_deep->deep_layer ().layout () != &edges.layout ()) { - - // create cell variants for magnification for the other input if needed - - const db::DeepLayer &other_layer = other_deep->deep_layer (); - - db::cell_variants_collector vars; - vars.collect (other_layer.layout (), other_layer.initial_cell ()); - - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (other_layer).separate_variants (vars); - - } - EdgeRelationFilter check (rel, d, options.metrics); check.set_include_zero (false); check.set_whole_edges (options.whole_edges); @@ -2071,7 +2055,6 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&edges.initial_cell ())); proc.set_base_verbosity (base_verbosity ()); - proc.set_vars (&vars); proc.set_threads (edges.store ()->threads ()); proc.run (&op, edges.layer (), other_deep ? other_deep->deep_layer ().layer () : edges.layer (), res->deep_layer ().layer ()); diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 897a14ec6..e21620e0c 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1799,18 +1799,7 @@ Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &no } compound_local_operation op (&node); - - // Prepare cell variants if needed - auto op_vars = op.vars (); - db::VariantsCollectorBase vc (op_vars); - if (op.wants_variants () && op_vars) { - vc.collect (polygons.layout (), polygons.initial_cell ()); - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (polygons).separate_variants (vc); - proc.set_vars (&vc); - } - - proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ()); + proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer (), true /*make_variants*/); return res.release (); } @@ -1863,17 +1852,7 @@ Output *region_cop_with_properties_impl (DeepRegion *region, db::CompoundRegionO } compound_local_operation_with_properties op (&node, prop_constraint, res->properties_repository (), subject_pr, intruder_prs); - - // Prepare cell variants if needed - db::VariantsCollectorBase vc (op.vars ()); - if (op.wants_variants ()) { - vc.collect (polygons.layout (), polygons.initial_cell ()); - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (polygons).separate_variants (vc); - proc.set_vars (&vc); - } - - proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ()); + proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer (), true /*make_variants*/); return res.release (); } @@ -1974,28 +1953,6 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons const db::DeepLayer &polygons = needs_merged_primary ? merged_deep_layer () : deep_layer (); - // create cell variants for magnification if needed - - db::cell_variants_collector vars; - vars.collect (polygons.layout (), polygons.initial_cell ()); - - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (polygons).separate_variants (vars); - - if (other_deep && &other_deep->deep_layer ().layout () != &polygons.layout ()) { - - // create cell variants for magnification for the other input if needed - - const db::DeepLayer &other_layer = other_deep->deep_layer (); - - db::cell_variants_collector vars; - vars.collect (other_layer.layout (), other_layer.initial_cell ()); - - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (other_layer).separate_variants (vars); - - } - EdgeRelationFilter check (rel, d, options.metrics); check.set_include_zero (false); check.set_whole_edges (options.whole_edges); @@ -2021,7 +1978,6 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons subject_breakout_cells, intruder_breakout_cells); configure_proc (proc); - proc.set_vars (&vars); proc.set_threads (polygons.store ()->threads ()); proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ()); @@ -2035,7 +1991,6 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons subject_breakout_cells, intruder_breakout_cells); configure_proc (proc); - proc.set_vars (&vars); proc.set_threads (polygons.store ()->threads ()); proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ()); diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 7fb293523..620c5f2fa 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -287,8 +287,31 @@ struct DeepShapeStore::LayoutHolder db::LayoutToNetlist *mp_l2n; }; + class VariantsCreatedListener + : public tl::Object + { + public: + VariantsCreatedListener (DeepShapeStore::LayoutHolder *lh, db::Layout *ly) + : mp_lh (lh) + { + ly->variants_created_event.add (this, &VariantsCreatedListener::variants_created); + } + + private: + void variants_created (const std::map > *var_map) + { + for (std::map >::const_iterator i = var_map->begin (); i != var_map->end (); ++i) { + for (std::map::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { + mp_lh->builder.register_variant (i->first, j->second); + } + } + } + + DeepShapeStore::LayoutHolder *mp_lh; + }; + LayoutHolder (const db::ICplxTrans &trans) - : refs (0), layout (false), builder (&layout, trans) + : refs (0), layout (false), builder (&layout, trans), variants_created (this, &layout) { // .. nothing yet .. } @@ -337,6 +360,9 @@ struct DeepShapeStore::LayoutHolder int refs; db::Layout layout; db::HierarchyBuilder builder; + +private: + VariantsCreatedListener variants_created; std::map > net_builders; std::map layer_refs; }; @@ -1048,17 +1074,6 @@ DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &s return create_custom_layer (si, &refs, trans); } -void -DeepShapeStore::issue_variants (unsigned int layout_index, const std::map > &var_map) -{ - db::HierarchyBuilder &builder = m_layouts [layout_index]->builder; - for (std::map >::const_iterator i = var_map.begin (); i != var_map.end (); ++i) { - for (std::map::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { - builder.register_variant (i->first, j->second); - } - } -} - const db::CellMapping & DeepShapeStore::internal_cell_mapping (unsigned int into_layout_index, unsigned int from_layout_index) { @@ -1268,6 +1283,13 @@ namespace }; } +void +DeepShapeStore::separate_variants (unsigned int layout_index, db::VariantsCollectorBase &coll) +{ + tl_assert (is_valid_layout_index (layout_index)); + layout (layout_index).separate_variants (coll, initial_cell (layout_index).cell_index ()); +} + void DeepShapeStore::insert (const DeepLayer &deep_layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) { diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 98c53c8fa..c53cc37d6 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -49,6 +49,7 @@ class Texts; class ShapeCollection; class NetBuilder; class LayoutToNetlist; +class VariantsCollectorBase; /** * @brief Represents a shape collection from the deep shape store @@ -561,20 +562,7 @@ public: * To use this method, first create a variant collector (db::cell_variant_collector) with the required * reducer and collect the variants. Then call this method on the desired layout index to create the variants. */ - template - void separate_variants (unsigned int layout_index, VarCollector &coll) - { - tl_assert (is_valid_layout_index (layout_index)); - - std::map > var_map; - coll.separate_variants (layout (layout_index), initial_cell (layout_index), &var_map); - if (var_map.empty ()) { - // nothing to do. - return; - } - - issue_variants (layout_index, var_map); - } + void separate_variants (unsigned int layout_index, db::VariantsCollectorBase &coll); /** * @brief Commits shapes for variants to the existing cell hierarchy diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index b93f96f35..636563fc0 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1143,7 +1143,7 @@ public: db::Box ref_box = db::box_convert () (*ref); for (db::CellInstArray::iterator n = inst->begin_touching (safe_box_enlarged (ref_box, m_dist - 1, m_dist - 1), inst_bc); !n.at_end (); ++n) { db::ICplxTrans tn = inst->complex_trans (*n); - db::Box region = ref_box.enlarged (db::Vector (m_dist, m_dist)).transformed (tn.inverted ()) & intruder_cell.bbox (m_intruder_layer) /*.enlarged (db::Vector (m_dist, m_dist))@@@*/; + db::Box region = ref_box.enlarged (db::Vector (m_dist, m_dist)).transformed (tn.inverted ()) & intruder_cell.bbox (m_intruder_layer); if (! region.empty ()) { add_shapes_from_intruder_inst (id1, intruder_cell, tn, inst_id, region); } @@ -1551,35 +1551,64 @@ size_t local_processor::get_progress () const } template -void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer) +void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer, bool make_variants) { std::vector ol, il; ol.push_back (output_layer); il.push_back (intruder_layer); - run (op, subject_layer, il, ol); + run (op, subject_layer, il, ol, make_variants); } template -void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector &output_layers) +void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector &output_layers, bool make_variants) { std::vector ol, il; il.push_back (intruder_layer); - run (op, subject_layer, il, output_layers); + run (op, subject_layer, il, output_layers, make_variants); } template -void local_processor::run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, unsigned int output_layer) +void local_processor::run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, unsigned int output_layer, bool make_variants) { std::vector ol; ol.push_back (output_layer); - run (op, subject_layer, intruder_layers, ol); + run (op, subject_layer, intruder_layers, ol, make_variants); } template -void local_processor::run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, const std::vector &output_layers) +void local_processor::run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, const std::vector &output_layers, bool make_variants) { tl::SelfTimer timer (tl::verbosity () > base_verbosity (), tl::to_string (tr ("Executing ")) + description (op)); + set_vars_owned (0); + + // Prepare cell variants if needed + if (make_variants) { + + tl::SelfTimer timer (tl::verbosity () > base_verbosity () + 10, tl::to_string (tr ("Cell variant formation"))); + + auto op_vars = op->vars (); + if (op_vars) { + + db::VariantsCollectorBase *coll = new db::VariantsCollectorBase (op_vars); + set_vars_owned (coll); + + coll->collect (*mp_subject_layout, *mp_subject_top); + mp_subject_layout->separate_variants (*coll, mp_subject_top->cell_index ()); + + if (mp_intruder_layout != mp_subject_layout) { + db::VariantsCollectorBase vci (op_vars); + vci.collect (*mp_intruder_layout, *mp_intruder_top); + if (vci.has_variants ()) { + // intruder layout needs to be the same one in that case - we do not want the secondary layout to be modified + throw tl::Exception (tl::to_string (tr ("Can't modify second layout for cell variant formation - this case is not supported as of now"))); + } + } + + } + + } + local_processor_contexts contexts; compute_contexts (contexts, op, subject_layer, intruder_layers); compute_results (contexts, op, output_layers); diff --git a/src/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index e0f6a9778..cffd05ee8 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -30,6 +30,7 @@ #include "dbLayout.h" #include "dbLocalOperation.h" #include "dbGenericShapeIterator.h" +#include "dbCellVariants.h" #include "tlThreadedWorkers.h" #include "tlProgress.h" @@ -44,8 +45,6 @@ namespace db { -class VariantsCollectorBase; - template class local_processor; template class local_processor_cell_context; template class local_processor_contexts; @@ -485,8 +484,9 @@ public: return m_boolean_core; } - void set_vars (const db::VariantsCollectorBase *vars) + void set_vars_owned (db::VariantsCollectorBase *vars) { + mp_vars_owned.reset (vars); mp_vars = vars; } @@ -517,6 +517,7 @@ private: bool m_boolean_core; int m_base_verbosity; const db::VariantsCollectorBase *mp_vars; + std::unique_ptr mp_vars_owned; mutable const db::Cell *mp_current_cell; }; @@ -528,10 +529,10 @@ public: local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set *breakout_cells = 0); local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set *subject_breakout_cells = 0, const std::set *intruder_breakout_cells = 0); - void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers); - void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector &output_layers); - void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, const std::vector &output_layers); - void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, unsigned int output_layer); + void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers, bool make_variants = true); + void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector &output_layers, bool make_variants = true); + void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, const std::vector &output_layers, bool make_variants = true); + void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, unsigned int output_layer, bool make_variants = true); void compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers) const; void compute_results (local_processor_contexts &contexts, const local_operation *op, const std::vector &output_layers) const; diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index a02ffa949..5ae8af700 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -33,6 +33,7 @@ #include "dbColdProxy.h" #include "dbLibraryManager.h" #include "dbLibrary.h" +#include "dbCellVariants.h" #include "dbRegion.h" #include "dbEdgePairs.h" #include "dbEdges.h" @@ -40,6 +41,7 @@ #include "dbCellMapping.h" #include "dbLayerMapping.h" #include "dbLayoutUtils.h" +#include "dbCellVariants.h" #include "tlTimer.h" #include "tlLog.h" #include "tlInternational.h" @@ -1810,6 +1812,15 @@ Layout::do_update () delete pr; } +void +Layout::separate_variants (db::VariantsCollectorBase &coll, cell_index_type initial_cell) +{ + std::map > var_table; + coll.separate_variants (*this, cell (initial_cell), &var_table); + + variants_created_event (&var_table); +} + static Layout::meta_info_map s_empty_meta; Layout::meta_info_iterator diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index 353ad2ad9..1ba18bdbd 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -71,6 +71,7 @@ class Texts; class Technology; class CellMapping; class LayerMapping; +class VariantsCollectorBase; template class generic_repository; typedef generic_repository GenericRepository; @@ -1657,6 +1658,15 @@ public: */ void update () const; + /** + * @brief Separates cell variants as given by the cell variant collector + * + * The cell variant collector must have been setup with the desired variants + * using "collect". The new cell variants will be created and a "variants_created" + * event is issued. + */ + void separate_variants (db::VariantsCollectorBase &coll, cell_index_type initial_cell); + /** * @brief Forces an update even if the layout is under construction * @@ -2068,6 +2078,12 @@ public: */ tl::Event technology_changed_event; + /** + * @brief This event is raised when cell variants are built + * It will specify a list of cells with their new variants. + */ + tl::event > *> variants_created_event; + protected: /** * @brief Establish the graph's internals according to the dirty flags diff --git a/src/db/db/dbLocalOperation.h b/src/db/db/dbLocalOperation.h index faccd6bf1..96dee1656 100644 --- a/src/db/db/dbLocalOperation.h +++ b/src/db/db/dbLocalOperation.h @@ -38,6 +38,7 @@ namespace db template class shape_interactions; class LocalProcessorBase; +class TransformationReducer; /** * @brief Indicates the desired behaviour for subject shapes for which there is no intruder @@ -117,6 +118,11 @@ public: */ virtual db::Coord dist () const { return 0; } + /** + * @brief Gets the cell variant reducer that indicates whether to build cell variants and which + */ + virtual const db::TransformationReducer *vars () const { return 0; } + protected: /** * @brief Computes the results from a given set of interacting shapes diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 76166715b..b1ffc8785 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -254,6 +254,11 @@ public: virtual std::string description () const; virtual void do_compute_local (db::Layout *layout, db::Cell *subject_cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const; + + virtual const db::TransformationReducer *vars () const { return &m_vars; } + +private: + db::MagnificationReducer m_vars; }; template @@ -270,8 +275,11 @@ public: virtual void do_compute_local (db::Layout *layout, db::Cell *subject_cell, const shape_interactions, db::object_with_properties > &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const; + virtual const db::TransformationReducer *vars () const { return &m_vars; } + private: mutable db::PropertyMapper m_pms, m_pmi; + db::MagnificationReducer m_vars; }; typedef check_local_operation CheckLocalOperation;