From 0cca9afc7e2a4c5ccecab26deb9a4e7f519858d7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 31 Oct 2024 21:34:17 +0100 Subject: [PATCH] Generalization: providing output functionality. --- src/db/db/dbEdgeNeighborhood.cc | 166 +++++++++++++++++++++---- src/db/db/dbEdgeNeighborhood.h | 85 +++++++++++-- src/db/db/gsiDeclDbEdgeNeighborhood.cc | 32 ++++- 3 files changed, 245 insertions(+), 38 deletions(-) diff --git a/src/db/db/dbEdgeNeighborhood.cc b/src/db/db/dbEdgeNeighborhood.cc index cc01131c5..88c6ca56e 100644 --- a/src/db/db/dbEdgeNeighborhood.cc +++ b/src/db/db/dbEdgeNeighborhood.cc @@ -27,6 +27,86 @@ namespace db { +// -------------------------------------------------------------------------------------------------- + +EdgeNeighborhoodVisitor::EdgeNeighborhoodVisitor () + : m_result_type (db::CompoundRegionOperationNode::ResultType::Edges) +{ + disconnect_outputs (); +} + +void +EdgeNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set *polygons) const +{ + disconnect_outputs (); + mp_polygons = polygons; +} + +void +EdgeNeighborhoodVisitor::connect_output (db::Layout *layout, std::unordered_set *polygons) const +{ + disconnect_outputs (); + mp_layout = layout; + mp_polygon_refs = polygons; +} + +void +EdgeNeighborhoodVisitor::connect_output (db::Layout * /*layout*/, std::unordered_set *edges) const +{ + disconnect_outputs (); + mp_edges = edges; +} + +void +EdgeNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set *edge_pairs) const +{ + disconnect_outputs (); + mp_edge_pairs = edge_pairs; +} + +void +EdgeNeighborhoodVisitor::disconnect_outputs () const +{ + mp_layout = 0; + mp_polygons = 0; + mp_polygon_refs = 0; + mp_edges = 0; + mp_edge_pairs = 0; +} + +void +EdgeNeighborhoodVisitor::output_polygon (const db::Polygon &poly) +{ + if (mp_polygons) { + mp_polygons->insert (poly); + } else if (mp_polygon_refs) { + tl_assert (mp_layout != 0); + mp_polygon_refs->insert (db::PolygonRef (poly, mp_layout->shape_repository ())); + } else { + throw tl::Exception (tl::to_string (tr ("EdgeNeighborhoodVisitor is not configured for edge output (use 'result_type=Edges')"))); + } +} + +void +EdgeNeighborhoodVisitor::output_edge (const db::Edge &edge) +{ + if (mp_edges == 0) { + throw tl::Exception (tl::to_string (tr ("EdgeNeighborhoodVisitor is not configured for edge output (use 'result_type=Edges')"))); + } + mp_edges->insert (edge); +} + +void +EdgeNeighborhoodVisitor::output_edge_pair (const db::EdgePair &edge_pair) +{ + if (mp_edge_pairs == 0) { + throw tl::Exception (tl::to_string (tr ("EdgeNeighborhoodVisitor is not configured for edge pair output (use 'result_type=EdgePairs')"))); + } + mp_edge_pairs->insert (edge_pair); +} + +// -------------------------------------------------------------------------------------------------- + EdgeNeighborhoodCompoundOperationNode::EdgeNeighborhoodCompoundOperationNode (const std::vector &children, EdgeNeighborhoodVisitor *visitor, db::Coord bext, db::Coord eext, db::Coord din, db::Coord dout) : CompoundRegionMultiInputOperationNode (children), m_bext (bext), m_eext (eext), m_din (din), m_dout (dout), mp_visitor (visitor) { @@ -172,54 +252,90 @@ EdgeNeighborhoodCompoundOperationNode::do_collect_neighbors (db::box_scanner2 &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const { - compute_local_impl (cache, layout, cell, interactions, results, proc); + compute_local_impl (cache, layout, cell, interactions, results, proc); } void EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const { - compute_local_impl (cache, layout, cell, interactions, results, proc); + compute_local_impl (cache, layout, cell, interactions, results, proc); } -template void -EdgeNeighborhoodCompoundOperationNode::compute_local_impl (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > & /*results*/, const db::LocalProcessorBase *proc) const +EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const +{ + compute_local_impl (cache, layout, cell, interactions, results, proc); +} + +void +EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const +{ + compute_local_impl (cache, layout, cell, interactions, results, proc); +} + +void +EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const +{ + compute_local_impl (cache, layout, cell, interactions, results, proc); +} + +void +EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const +{ + compute_local_impl (cache, layout, cell, interactions, results, proc); +} + +template +void +EdgeNeighborhoodCompoundOperationNode::compute_local_impl (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase *proc) const { if (! mp_visitor) { return; } tl_assert (interactions.num_subjects () == 1); + tl_assert (! results.empty ()); - db::box_scanner2 scanner; + try { - std::list edges; - std::list polygons; + mp_visitor->connect_output (layout, &results.front ()); - for (unsigned int i = 0; i < children (); ++i) { + db::box_scanner2 scanner; - std::vector > others; - others.push_back (std::unordered_set ()); + std::list edges; + std::list polygons; - shape_interactions computed_interactions; - child (i)->compute_local (cache, layout, cell, interactions_for_child (interactions, i, computed_interactions), others, proc); + for (unsigned int i = 0; i < children (); ++i) { + + std::vector > others; + others.push_back (std::unordered_set ()); + + shape_interactions computed_interactions; + child (i)->compute_local (cache, layout, cell, interactions_for_child (interactions, i, computed_interactions), others, proc); + + for (auto p = others.front ().begin (); p != others.front ().end (); ++p) { + polygons.push_back (p->instantiate ()); + scanner.insert2 (&polygons.back (), i); + } - for (auto p = others.front ().begin (); p != others.front ().end (); ++p) { - polygons.push_back (p->instantiate ()); - scanner.insert2 (&polygons.back (), i); } - } + const T &pr = interactions.begin_subjects ()->second; + unsigned int ie = 0; + for (auto e = pr.begin_edge (); ! e.at_end (); ++e, ++ie) { + edges.push_back (*e); + scanner.insert1 (&edges.back (), ie); + } - const T &pr = interactions.begin_subjects ()->second; - unsigned int ie = 0; - for (auto e = pr.begin_edge (); ! e.at_end (); ++e, ++ie) { - edges.push_back (*e); - scanner.insert1 (&edges.back (), ie); - } + const_cast (mp_visitor.get ())->begin_polygon (layout, cell, pr.instantiate ()); + do_collect_neighbors (scanner, layout, cell); + const_cast (mp_visitor.get ())->end_polygon (); - const_cast (mp_visitor.get ())->begin_polygon (layout, cell, pr.instantiate ()); - do_collect_neighbors (scanner, layout, cell); - const_cast (mp_visitor.get ())->end_polygon (); + mp_visitor->disconnect_outputs (); + + } catch (...) { + mp_visitor->disconnect_outputs (); + throw; + } } } diff --git a/src/db/db/dbEdgeNeighborhood.h b/src/db/db/dbEdgeNeighborhood.h index 6eec7ac47..3566b336d 100644 --- a/src/db/db/dbEdgeNeighborhood.h +++ b/src/db/db/dbEdgeNeighborhood.h @@ -48,13 +48,38 @@ public: /** * @brief Constructor */ - EdgeNeighborhoodVisitor () { } + EdgeNeighborhoodVisitor (); /** * @brief Destructor */ virtual ~EdgeNeighborhoodVisitor () { } + /** + * @brief Configure the polygon output + */ + void connect_output (db::Layout * /*layout*/, std::unordered_set *polygons) const; + + /** + * @brief Configure the polygon ref output + */ + void connect_output (db::Layout *layout, std::unordered_set *polygons) const; + + /** + * @brief Configure the edge output + */ + void connect_output (db::Layout * /*layout*/, std::unordered_set *edges) const; + + /** + * @brief Configure the edge pair output + */ + void connect_output (db::Layout * /*layout*/, std::unordered_set *edge_pairs) const; + + /** + * @brief Disconnects output + */ + void disconnect_outputs () const; + /** * @brief Event handler called when a new polygon is encountered * Following this event, the edges with their neighborhood are reported. @@ -71,6 +96,48 @@ public: * @brief Event handler for each edge plus it's neighborhood */ virtual void on_edge (const db::Layout * /*layout*/, const db::Cell * /*cell*/, const db::Edge & /*edge*/, const neighbors_type & /*neighbors*/) { } + + /** + * @brief Sets the result type + */ + void set_result_type (db::CompoundRegionOperationNode::ResultType result_type) + { + m_result_type = result_type; + } + + /** + * @brief Gets the result type + */ + db::CompoundRegionOperationNode::ResultType result_type () const + { + return m_result_type; + } + + /** + * @brief Delivers a polygon + * This function is only permitted if the result type is Region. + */ + void output_polygon (const db::Polygon &poly); + + /** + * @brief Delivers an edge + * This function is only permitted if the result type is Edges. + */ + void output_edge (const db::Edge &edge); + + /** + * @brief Delivers an edge pair object + * This function is only permitted if the result type is EdgePairs. + */ + void output_edge_pair (const db::EdgePair &edge_pair); + +private: + db::CompoundRegionOperationNode::ResultType m_result_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; }; /** @@ -84,7 +151,7 @@ public: virtual ResultType result_type () const { - return CompoundRegionOperationNode::Edges; + return mp_visitor ? mp_visitor->result_type () : CompoundRegionOperationNode::Edges; } virtual bool wants_caching () const @@ -98,12 +165,10 @@ protected: virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; - - // not implemented - virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { } - virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { } - virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { } - virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { } + virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; + virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; + virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; + virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const; private: db::Coord m_bext, m_eext, m_din, m_dout; @@ -111,8 +176,8 @@ private: void do_collect_neighbors (db::box_scanner2 &scanner, const db::Layout *layout, const db::Cell *cell) const; - 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; + 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/gsiDeclDbEdgeNeighborhood.cc b/src/db/db/gsiDeclDbEdgeNeighborhood.cc index 1cbed771e..b3b770d7b 100644 --- a/src/db/db/gsiDeclDbEdgeNeighborhood.cc +++ b/src/db/db/gsiDeclDbEdgeNeighborhood.cc @@ -59,7 +59,7 @@ public: gsi::Callback f_on_edge; - void issue_begin_polygon (const db::Layout *, const db::Cell *, const db::Polygon &poly) + void issue_begin_polygon (const db::Layout *, const db::Cell *, const db::Polygon &) { // just for signature } @@ -148,7 +148,7 @@ Class decl_EdgeNeighborhoodVisitorImpl (decl_E "\n" "@code\n" "[\n" - " [ [ from, to ], { input_index => polygons }\n" + " [ [ from, to ], { input_index => polygons } ]\n" "]\n" "@/code\n" "\n" @@ -168,6 +168,30 @@ Class decl_EdgeNeighborhoodVisitorImpl (decl_E gsi::callback ("end_polygon", &EdgeNeighborhoodVisitorImpl::issue_end_polygon, &EdgeNeighborhoodVisitorImpl::f_end_polygon, "@brief Is called after the polygon\n" "See \\begin_polygon for a description of this protocol." + ) + + gsi::method ("output", &EdgeNeighborhoodVisitorImpl::output_polygon, gsi::arg ("polygon"), + "@brief Outputs a polygon\n" + "Use this method from one of the callbacks (\\on_edge, \\begin_polygon, \\end_polygon) to deliver a polygon. " + "Note that you have to configure the result type as 'Region' on construction of the visitor before being able to do so." + ) + + gsi::method ("output", &EdgeNeighborhoodVisitorImpl::output_edge, gsi::arg ("edge"), + "@brief Outputs an edge\n" + "Use this method from one of the callbacks (\\on_edge, \\begin_polygon, \\end_polygon) to deliver a polygon. " + "Note that you have to configure the result type as 'Edges' on construction of the visitor before being able to do so." + ) + + gsi::method ("output", &EdgeNeighborhoodVisitorImpl::output_edge_pair, gsi::arg ("edge_pair"), + "@brief Outputs an edge pair\n" + "Use this method from one of the callbacks (\\on_edge, \\begin_polygon, \\end_polygon) to deliver a polygon. " + "Note that you have to configure the result type as 'EdgePairs' on construction of the visitor before being able to do so." + ) + + gsi::method ("result_type=", &EdgeNeighborhoodVisitorImpl::set_result_type, gsi::arg ("result_type"), + "@brief Configures the result type\n" + "Use this method to indicate what type of result you want to deliver. You can use the corresponding 'output' method then to " + "deliver result shapes from one the callbacks (\\on_edge, \\begin_polygon, \\end_polygon). Set this attribute when you create " + "the visitor object. This attribute does not need to be set if no output is indended to be delivered." + ) + + gsi::method ("result_type", &EdgeNeighborhoodVisitorImpl::result_type, + "@brief Gets the result type\n" ), "@brief A visitor for the neighborhood of edges in the input\n" "\n" @@ -176,7 +200,7 @@ Class decl_EdgeNeighborhoodVisitorImpl (decl_E "\n" "See \\on_edge for the description of the events delivered." "\n" - "This class has been introduced in version 0.xx.\n" // @@@ + "This class has been introduced in version 0.29.9.\n" ); // --------------------------------------------------------------------------------- @@ -197,6 +221,8 @@ gsi::ClassExt decl_CompoundRegionOperationNode_ "@param eext The search window extension to use at the edge beginning.\n" "@param din The search window extension to use at the edge beginning.\n" "@param dout The search window extension to use at the edge beginning.\n" + "\n" + "This constructor has been introduced in version 0.29.9.\n" ) );