diff --git a/src/db/db/dbCellVariants.cc b/src/db/db/dbCellVariants.cc index 74ab634a4..f4d928289 100644 --- a/src/db/db/dbCellVariants.cc +++ b/src/db/db/dbCellVariants.cc @@ -712,6 +712,28 @@ VariantsCollectorBase::create_var_instances_tl_invariant (db::Cell &in_cell, std // ------------------------------------------------------------------------------------------ +TransformationReducer * +make_reducer (ReducerType type) +{ + + switch (type) { + case Orientation: + return new OrientationReducer (); + case Orthogonal: + return new OrthogonalTransformationReducer (); + case Magnification: + return new MagnificationReducer (); + case XYAnisotropyAndMagnification: + return new XYAnisotropyAndMagnificationReducer (); + case MagnificationAndOrientation: + return new MagnificationAndOrientationReducer (); + default: + return 0; + } +} + +// ------------------------------------------------------------------------------------------ + VariantStatistics::VariantStatistics () : mp_red () { diff --git a/src/db/db/dbCellVariants.h b/src/db/db/dbCellVariants.h index 18e21f11a..b33e40c81 100644 --- a/src/db/db/dbCellVariants.h +++ b/src/db/db/dbCellVariants.h @@ -166,6 +166,51 @@ private: int64_t m_grid; }; +/** + * @brief An enum describing a reducer type + * + * This enum is used to create a generic reducer (parameterless) from the code. + */ +enum ReducerType +{ + /** + * @brief No specific reducer + */ + NoReducer = 0, + + /** + * @brief Rotation/mirror variants + */ + Orientation = 1, + + /** + * @brief Orthogonal transformations (rotations of multiple of 90 degree) variants + */ + Orthogonal = 2, + + /** + * @brief Scaling variants + */ + Magnification = 3, + + /** + * @brief Scaling and x/y assymmetry variants (i.e. anisotropic size) + */ + XYAnisotropyAndMagnification = 4, + + /** + * @brief Scaling and orientation variants + */ + MagnificationAndOrientation = 5 +}; + +/** + * @brief Creates a TransformationReducer from the type enum + * + * This function returns 0 if the type is NoReducer or invalid. + */ +DB_PUBLIC TransformationReducer *make_reducer (ReducerType type); + /** * @brief A class computing variants for cells according to a given criterion * diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index cd9f8dcad..80445387f 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -302,7 +302,7 @@ CompoundTransformationReducer::is_translation_invariant () const // --------------------------------------------------------------------------------------------- -CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (const std::vector &children) +CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (const std::vector &children, bool no_init) { for (std::vector::const_iterator c = children.begin (); c != children.end (); ++c) { (*c)->keep (); @@ -362,6 +362,11 @@ CompoundRegionMultiInputOperationNode::init () for (tl::shared_collection::iterator i = m_children.begin (); i != m_children.end (); ++i) { m_vars.add (i->vars ()); } + + // add the local variant reducer + if (local_vars ()) { + m_vars.add (local_vars ()); + } } CompoundRegionMultiInputOperationNode::~CompoundRegionMultiInputOperationNode () diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h index 4f109553a..78c8661c3 100644 --- a/src/db/db/dbCompoundOperation.h +++ b/src/db/db/dbCompoundOperation.h @@ -453,7 +453,7 @@ class DB_PUBLIC CompoundRegionMultiInputOperationNode : public CompoundRegionOperationNode { public: - CompoundRegionMultiInputOperationNode (const std::vector &children); + CompoundRegionMultiInputOperationNode (const std::vector &children, bool no_init = false); CompoundRegionMultiInputOperationNode (); CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *child); CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b); @@ -521,14 +521,16 @@ protected: CompoundRegionOperationNode *child (unsigned int index); const CompoundRegionOperationNode *child (unsigned int index) const; + virtual const TransformationReducer *local_vars () const { return 0; } + + void init (); + private: tl::shared_collection m_children; // maps child#,layer# to layer# of child: std::map, unsigned int> m_map_layer_to_child; std::vector m_inputs; CompoundTransformationReducer m_vars; - - void init (); }; diff --git a/src/db/db/dbPolygonNeighborhood.cc b/src/db/db/dbPolygonNeighborhood.cc index 21a7a9696..35fe0b384 100644 --- a/src/db/db/dbPolygonNeighborhood.cc +++ b/src/db/db/dbPolygonNeighborhood.cc @@ -28,38 +28,42 @@ namespace db { PolygonNeighborhoodVisitor::PolygonNeighborhoodVisitor () - : m_result_type (db::CompoundRegionOperationNode::ResultType::Edges) + : m_result_type (db::CompoundRegionOperationNode::ResultType::Edges), m_variant_type (db::NoReducer) { disconnect_outputs (); } void -PolygonNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set *polygons) const +PolygonNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set *polygons, const db::ICplxTrans &trans) const { disconnect_outputs (); mp_polygons = polygons; + m_trans = trans; } void -PolygonNeighborhoodVisitor::connect_output (db::Layout *layout, std::unordered_set *polygons) const +PolygonNeighborhoodVisitor::connect_output (db::Layout *layout, std::unordered_set *polygons, const db::ICplxTrans &trans) const { disconnect_outputs (); mp_layout = layout; mp_polygon_refs = polygons; + m_trans = trans; } void -PolygonNeighborhoodVisitor::connect_output (db::Layout * /*layout*/, std::unordered_set *edges) const +PolygonNeighborhoodVisitor::connect_output (db::Layout * /*layout*/, std::unordered_set *edges, const db::ICplxTrans &trans) const { disconnect_outputs (); mp_edges = edges; + m_trans = trans; } void -PolygonNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set *edge_pairs) const +PolygonNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set *edge_pairs, const db::ICplxTrans &trans) const { disconnect_outputs (); mp_edge_pairs = edge_pairs; + m_trans = trans; } void @@ -76,10 +80,10 @@ void PolygonNeighborhoodVisitor::output_polygon (const db::PolygonWithProperties &poly) { if (mp_polygons) { - mp_polygons->insert (poly); + mp_polygons->insert (poly.transformed (m_trans)); } else if (mp_polygon_refs) { tl_assert (mp_layout != 0); - mp_polygon_refs->insert (db::PolygonRefWithProperties (db::PolygonRef (poly, mp_layout->shape_repository ()), poly.properties_id ())); + mp_polygon_refs->insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (m_trans), mp_layout->shape_repository ()), poly.properties_id ())); } else { throw tl::Exception (tl::to_string (tr ("PolygonNeighborhoodVisitor is not configured for edge output (use 'result_type=Edges')"))); } @@ -91,7 +95,7 @@ PolygonNeighborhoodVisitor::output_edge (const db::EdgeWithProperties &edge) if (mp_edges == 0) { throw tl::Exception (tl::to_string (tr ("PolygonNeighborhoodVisitor is not configured for edge output (use 'result_type=Edges')"))); } - mp_edges->insert (edge); + mp_edges->insert (edge.transformed (m_trans)); } void @@ -100,16 +104,22 @@ PolygonNeighborhoodVisitor::output_edge_pair (const db::EdgePairWithProperties & if (mp_edge_pairs == 0) { throw tl::Exception (tl::to_string (tr ("PolygonNeighborhoodVisitor is not configured for edge pair output (use 'result_type=EdgePairs')"))); } - mp_edge_pairs->insert (edge_pair); + mp_edge_pairs->insert (edge_pair.transformed (m_trans)); } // -------------------------------------------------------------------------------------------------- PolygonNeighborhoodCompoundOperationNode::PolygonNeighborhoodCompoundOperationNode (const std::vector &children, PolygonNeighborhoodVisitor *visitor, db::Coord dist) - : CompoundRegionMultiInputOperationNode (children), m_dist (dist), mp_visitor (visitor) + : CompoundRegionMultiInputOperationNode (children, true /*no implicit init()*/), + m_dist (dist), mp_visitor (visitor) { tl_assert (visitor != 0); visitor->keep (); + + m_vars.reset (db::make_reducer (visitor->variant_type ())); + + // must be called after local_vars() is available + init (); } db::Coord @@ -170,12 +180,19 @@ PolygonNeighborhoodCompoundOperationNode::compute_local_impl (CompoundRegionOper tl_assert (interactions.num_subjects () == 1); tl_assert (! results.empty ()); + db::ICplxTrans var_trans, var_trans_inv; + if (proc->vars ()) { + var_trans_inv = proc->vars ()->single_variant_transformation (cell->cell_index ()); + var_trans = var_trans_inv.inverted (); + } + try { - mp_visitor->connect_output (layout, &results.front ()); + mp_visitor->connect_output (layout, &results.front (), var_trans_inv); const T &pr = interactions.begin_subjects ()->second; db::PolygonWithProperties subject (pr.instantiate (), pr.properties_id ()); + subject.transform (var_trans); PolygonNeighborhoodVisitor::neighbors_type neighbors; @@ -191,6 +208,7 @@ PolygonNeighborhoodCompoundOperationNode::compute_local_impl (CompoundRegionOper for (auto p = others.front ().begin (); p != others.front ().end (); ++p) { n.push_back (db::PolygonWithProperties (p->instantiate (), p->properties_id ())); + n.back ().transform (var_trans); } } diff --git a/src/db/db/dbPolygonNeighborhood.h b/src/db/db/dbPolygonNeighborhood.h index 17bd13178..25314f6dd 100644 --- a/src/db/db/dbPolygonNeighborhood.h +++ b/src/db/db/dbPolygonNeighborhood.h @@ -58,22 +58,22 @@ public: /** * @brief Configure the polygon output */ - void connect_output (db::Layout * /*layout*/, std::unordered_set *polygons) const; + void connect_output (db::Layout * /*layout*/, std::unordered_set *polygons, const db::ICplxTrans &trans) const; /** * @brief Configure the polygon ref output */ - void connect_output (db::Layout *layout, std::unordered_set *polygons) const; + void connect_output (db::Layout *layout, std::unordered_set *polygons, const db::ICplxTrans &trans) const; /** * @brief Configure the edge output */ - void connect_output (db::Layout * /*layout*/, std::unordered_set *edges) const; + void connect_output (db::Layout * /*layout*/, std::unordered_set *edges, const db::ICplxTrans &trans) const; /** * @brief Configure the edge pair output */ - void connect_output (db::Layout * /*layout*/, std::unordered_set *edge_pairs) const; + void connect_output (db::Layout * /*layout*/, std::unordered_set *edge_pairs, const db::ICplxTrans &trans) const; /** * @brief Disconnects output @@ -102,6 +102,22 @@ public: return m_result_type; } + /** + * @brief Sets the variant type + */ + void set_variant_type (db::ReducerType variant_type) + { + m_variant_type = variant_type; + } + + /** + * @brief Gets the variant type + */ + db::ReducerType variant_type () const + { + return m_variant_type; + } + /** * @brief Delivers a polygon * This function is only permitted if the result type is Region. @@ -122,11 +138,13 @@ public: private: db::CompoundRegionOperationNode::ResultType m_result_type; + db::ReducerType m_variant_type; mutable std::unordered_set *mp_polygons; mutable std::unordered_set *mp_polygon_refs; mutable std::unordered_set *mp_edges; mutable std::unordered_set *mp_edge_pairs; mutable db::Layout *mp_layout; + mutable db::ICplxTrans m_trans; }; /** @@ -148,6 +166,11 @@ public: return false; } + virtual const TransformationReducer *local_vars () const + { + return m_vars.get (); + } + protected: virtual db::Coord computed_dist () const; virtual std::string generated_description () const; @@ -162,6 +185,7 @@ protected: private: db::Coord m_dist; tl::weak_ptr mp_visitor; + std::unique_ptr m_vars; template void compute_local_impl (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index 4b4bc70a5..0e2f6f119 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -22,6 +22,7 @@ #include "gsiDecl.h" #include "gsiDeclDbMetaInfo.h" +#include "gsiEnums.h" #include "gsiDeclDbHelpers.h" #include "dbLayout.h" @@ -4655,5 +4656,39 @@ Class decl_DCellInstArray ("db", "DCellInstArray", "This class has been introduced in version 0.25." ); +gsi::Enum decl_VariantType ("db", "VariantType", + gsi::enum_const ("NoVariants", db::NoReducer, + "@brief No variants needed." + ) + + gsi::enum_const ("Orientation", db::Orientation, + "@brief Orientation variants needed.\n" + "For example, the edge orientation selection operation needs this variant type." + ) + + gsi::enum_const ("Orthogonal", db::Orthogonal, + "@brief Orthogonal transformations (rotations by multiples of 90 degree) need variants.\n" + "For example, the diagonal edge selection operation needs this variant type." + ) + + gsi::enum_const ("Magnification", db::Magnification, + "@brief Scaling variants needed.\n" + "For example, distance measurements or the isotropic sizing operations needs this variant type." + ) + + gsi::enum_const ("XYAnisotropyAndMagnification", db::XYAnisotropyAndMagnification, + "@brief Scaling and anisotropy variants needed.\n" + "For example, the anisotropic sizing operation needs this variant type." + ) + + gsi::enum_const ("MagnificationAndOrientation", db::MagnificationAndOrientation, + "@brief Scaling and orientation variants needed.\n" + "For example, the 'move' operation needs this variant type." + ), + "@brief This class represents the cell variant type for various methods.\n" + "\n" + "Cell variants are needed in hierarchical applications, when operations are to be " + "performed on cell level, but the operations are not transformation invariant.\n" + "In that case, a variant type needs to be specified in order to make the algorithm " + "separate the cells by their absolute orientation or by their accumulated magnification.\n" + "\n" + "This enum has been introduced in version 0.30.2." +); + } diff --git a/src/db/db/gsiDeclDbPolygonNeighborhood.cc b/src/db/db/gsiDeclDbPolygonNeighborhood.cc index 37c0ffded..b8c9ebb5c 100644 --- a/src/db/db/gsiDeclDbPolygonNeighborhood.cc +++ b/src/db/db/gsiDeclDbPolygonNeighborhood.cc @@ -109,6 +109,20 @@ Class decl_PolygonNeighborhoodVisitorImpl ( ) + gsi::method ("result_type", &PolygonNeighborhoodVisitorImpl::result_type, "@brief Gets the result type\n" + ) + + gsi::method ("variant_type=", &PolygonNeighborhoodVisitorImpl::set_variant_type, gsi::arg ("variant_type"), + "@brief Configures the variant type\n" + "The variant type configures transformation variant formation. The polygons presented to the visitor are " + "normalized to the given variant type. For example, specify \\VariantType#Orientation to force orientation variants " + "in the cell tree. Polygons presented to the visitor are normalized to 'as if top' orientation with this variant type.\n" + "\n" + "This property was introduced in version 0.30.2." + ) + + gsi::method ("variant_type", &PolygonNeighborhoodVisitorImpl::variant_type, + "@brief Gets the variant type\n" + "See \\variant_type= for a description of this property.\n" + "\n" + "This property was introduced in version 0.30.2." ), "@brief A visitor for the neighborhood of polygons in the input\n" "\n"