From 422c88207c191c8de4b65998b794948e1743309f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 21 Oct 2024 21:50:35 +0200 Subject: [PATCH] WIP --- src/db/db/db.pro | 3 + src/db/db/dbCompoundOperation.h | 30 +++-- src/db/db/dbEdgeNeighborhood.cc | 107 +++++++++++++++++ src/db/db/dbEdgeNeighborhood.h | 106 +++++++++++++++++ src/db/db/gsiDeclDbEdgeNeighborhood.cc | 159 +++++++++++++++++++++++++ 5 files changed, 395 insertions(+), 10 deletions(-) create mode 100644 src/db/db/dbEdgeNeighborhood.cc create mode 100644 src/db/db/dbEdgeNeighborhood.h create mode 100644 src/db/db/gsiDeclDbEdgeNeighborhood.cc diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 299f029e3..81f25683d 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -23,6 +23,7 @@ SOURCES = \ dbCommonReader.cc \ dbCompoundOperation.cc \ dbEdge.cc \ + dbEdgeNeighborhood.cc \ dbEdgePair.cc \ dbEdgePairFilters.cc \ dbEdgePairRelations.cc \ @@ -119,6 +120,7 @@ SOURCES = \ gsiDeclDbCommonStreamOptions.cc \ gsiDeclDbCompoundOperation.cc \ gsiDeclDbEdge.cc \ + gsiDeclDbEdgeNeighborhood.cc \ gsiDeclDbEdgePair.cc \ gsiDeclDbEdgePairs.cc \ gsiDeclDbEdgeProcessor.cc \ @@ -249,6 +251,7 @@ HEADERS = \ dbCommonReader.h \ dbCompoundOperation.h \ dbEdge.h \ + dbEdgeNeighborhood.h \ dbEdgePair.h \ dbEdgePairFilters.h \ dbEdgePairRelations.h \ diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h index 9047b8e09..cdb125e51 100644 --- a/src/db/db/dbCompoundOperation.h +++ b/src/db/db/dbCompoundOperation.h @@ -266,6 +266,7 @@ protected: virtual db::Coord computed_dist () const = 0; virtual std::string generated_description () const; + virtual bool wants_caching () const { return true; } private: std::string m_description; @@ -276,23 +277,32 @@ private: { // TODO: confine caching to those nodes which need it. - std::pair > *> cp = cache->get (this); + if (wants_caching ()) { - if (! cp.first) { + std::pair > *> cp = cache->get (this); - std::vector > uncached_results; - uncached_results.resize (results.size ()); + if (! cp.first) { - do_compute_local (cache, layout, cell, interactions, uncached_results, proc); + std::vector > uncached_results; + uncached_results.resize (results.size ()); - cp.second->swap (uncached_results); + do_compute_local (cache, layout, cell, interactions, uncached_results, proc); + + cp.second->swap (uncached_results); + + } + + tl_assert (results.size () == cp.second->size ()); + for (size_t r = 0; r < results.size (); ++r) { + results[r].insert ((*cp.second)[r].begin (), (*cp.second)[r].end ()); + } + + } else { + + do_compute_local (cache, layout, cell, interactions, results, proc); } - tl_assert (results.size () == cp.second->size ()); - for (size_t r = 0; r < results.size (); ++r) { - results[r].insert ((*cp.second)[r].begin (), (*cp.second)[r].end ()); - } } }; diff --git a/src/db/db/dbEdgeNeighborhood.cc b/src/db/db/dbEdgeNeighborhood.cc new file mode 100644 index 000000000..7aab8d821 --- /dev/null +++ b/src/db/db/dbEdgeNeighborhood.cc @@ -0,0 +1,107 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbEdgeNeighborhood.h" +#include "dbBoxScanner.h" + +namespace db +{ + +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) +{ + tl_assert (visitor != 0); + visitor->keep (); +} + +db::Coord +EdgeNeighborhoodCompoundOperationNode::computed_dist () const +{ + return std::max (std::max (m_bext, m_eext), std::max (m_din, m_dout)); +} + +std::string +EdgeNeighborhoodCompoundOperationNode::generated_description () const +{ + return tl::to_string (tr ("Neighborhood collector")); +} + +void +EdgeNeighborhoodCompoundOperationNode::do_collect_neighbors (db::box_scanner2 &scanner, const db::Layout *layout, const db::Cell *cell) const +{ + + +} + +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 +{ + tl_assert (interactions.num_subjects () == 1); + + db::box_scanner2 scanner; + + std::list edges; + std::list polygons; + + for (auto i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) { + db::PolygonRef pr (i->second.second); + polygons.push_back (pr.instantiate ()); + scanner.insert2 (&polygons.back (), i->second.first); + } + + const db::PolygonRef &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); + } + + do_collect_neighbors (scanner, layout, cell); +} + +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 +{ + tl_assert (interactions.num_subjects () == 1); + + db::box_scanner2 scanner; + + std::list edges; + std::list polygons; + + for (auto i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) { + polygons.push_back (i->second.second); + scanner.insert2 (&polygons.back (), i->second.first); + } + + const db::Polygon &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); + } + + do_collect_neighbors (scanner, layout, cell); +} + +} + diff --git a/src/db/db/dbEdgeNeighborhood.h b/src/db/db/dbEdgeNeighborhood.h new file mode 100644 index 000000000..cef890085 --- /dev/null +++ b/src/db/db/dbEdgeNeighborhood.h @@ -0,0 +1,106 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + + +#ifndef HDR_dbEdgeNeighborhood +#define HDR_dbEdgeNeighborhood + +#include "dbCommon.h" +#include "dbCompoundOperation.h" +#include "dbBoxScanner.h" + +namespace db +{ + +/** + * @brief A visitor for the neighbors of an edge + */ +class DB_PUBLIC EdgeNeighborhoodVisitor + : public gsi::ObjectBase, public tl::Object +{ +public: + typedef std::pair position_interval_type; + typedef unsigned int input_key_type; + typedef std::list neighbor_shapes_type; + typedef std::map neighbors_per_interval_type; + typedef std::vector > neighbors_type; + + /** + * @brief Constructor + */ + EdgeNeighborhoodVisitor () { } + + /** + * @brief Destructor + */ + virtual ~EdgeNeighborhoodVisitor () { } + + /** + * @brief Event handler for each edge plus it's neighborhood + */ + void on_edge (const db::Layout *layout, const db::Cell *cell, const db::Edge &edge, const neighbors_type &neighbors); +}; + +/** + * @brief A local operation for implementation of the neighborhood visitor + */ +class DB_PUBLIC EdgeNeighborhoodCompoundOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + EdgeNeighborhoodCompoundOperationNode (const std::vector &children, EdgeNeighborhoodVisitor *visitor, const db::Coord bext, db::Coord eext, db::Coord din, db::Coord dout); + + virtual ResultType result_type () const + { + return CompoundRegionOperationNode::Edges; + } + + virtual bool wants_caching () const + { + return false; + } + +protected: + virtual db::Coord computed_dist () const; + virtual std::string generated_description () 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; + + // 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 { } + +private: + db::Coord m_bext, m_eext, m_din, m_dout; + tl::weak_ptr mp_visitor; + + void do_collect_neighbors (db::box_scanner2 &scanner, const db::Layout *layout, const db::Cell *cell) const; +}; + +} + +#endif + diff --git a/src/db/db/gsiDeclDbEdgeNeighborhood.cc b/src/db/db/gsiDeclDbEdgeNeighborhood.cc new file mode 100644 index 000000000..947b0322a --- /dev/null +++ b/src/db/db/gsiDeclDbEdgeNeighborhood.cc @@ -0,0 +1,159 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "gsiDecl.h" +#include "gsiEnums.h" + +#include "tlThreads.h" +#include "dbEdgeNeighborhood.h" + +namespace gsi +{ + +// --------------------------------------------------------------------------------- +// EdgeFilter binding + +class EdgeNeighborhoodVisitorImpl + : public db::EdgeNeighborhoodVisitor +{ +public: + EdgeNeighborhoodVisitorImpl () { } + + void issue_on_edge (const db::Layout *, const db::Cell *, const db::Edge &, const tl::Variant &) + { + // just for signature + } + + void on_edge (const db::Layout *layout, const db::Cell *cell, const db::Edge &edge, const db::EdgeNeighborhoodVisitor::neighbors_type &neighbors) + { + if (f_on_edge.can_issue ()) { + + tl::Variant neighborhood = build_neighbors (neighbors); + + // NOTE: as scripts are potentially thread unsafe, we lock here + tl::MutexLocker locker (&m_lock); + return f_on_edge.issue (&EdgeNeighborhoodVisitorImpl::issue_on_edge, layout, cell, edge, neighborhood); + + } + } + + gsi::Callback f_on_edge; + + static tl::Variant build_neighbors (const db::EdgeNeighborhoodVisitor::neighbors_type &neighbors) + { + tl::Variant result; + result.set_list (); + + for (auto n = neighbors.begin (); n != neighbors.end (); ++n) { + + tl::Variant row; + row.set_list (); + + tl::Variant interval; + interval.set_list (); + interval.push (n->first.first); + interval.push (n->first.second); + row.push (interval); + + tl::Variant nmap; + nmap.set_array (); + + for (auto nn = n->second.begin (); nn != n->second.end (); ++nn) { + nmap.insert (tl::Variant (nn->first), tl::Variant (nn->second)); + } + + row.push (nmap); + + result.push (row); + + } + + return result; + } + +private: + // No copying + EdgeNeighborhoodVisitorImpl &operator= (const EdgeNeighborhoodVisitorImpl &); + EdgeNeighborhoodVisitorImpl (const EdgeNeighborhoodVisitorImpl &); + + tl::Mutex m_lock; +}; + +Class decl_EdgeNeighborhoodVisitorImpl ("db", "EdgeNeighborhoodVisitor", + gsi::callback ("on_edge", &EdgeNeighborhoodVisitorImpl::issue_on_edge, &EdgeNeighborhoodVisitorImpl::f_on_edge, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("edge"), gsi::arg ("neighborhood"), + "@brief Is called for each edge with the edge neighbors\n" + "This method is called for every edge on the input region. It delivers the edge and the edge neighborhood. " + "The edge neighborhood is classified in intervals along the edge. The intervals are given by a range of " + "positions along the edge - 0.0 being the beginning of the edge and positive values towards the end of the edge. " + "For 'bext' and 'eext' larger than zero (see " + "\\EdgeNeighborhoodCompoundOperationNode), the position can be negative or larger than the edge length.\n" + "\n" + "The structure of the neighbors is:\n" + "\n" + "@code\n" + "[\n" + " [ [ from, to ], { input_index => polygons }\n" + "]\n" + "@/code\n" + "\n" + "'from' and 'to' are the positions of the interval, 'input_index' is the index of the input the neighbors are on " + "(see 'children' argument of \\EdgeNeighborhoodCompoundOperationNode constructor), 'prop_id' is the properties ID of " + "the neighbors and 'polygons' is a list of polygons describing the neighborhood.\n" + "The polygons are projected on the edge - i.e. they are in a coordinate system where the edge is horizonal and " + "goes from (0,0) to (length,0).\n" + "\n" + "The polygons are boxes for manhattan input and trapezoids in the general case.\n" + ), + "@brief A visitor for the neighborhood of edges in the input\n" + "\n" + "Objects of this class are passed to \\EdgeNeighborhoodCompoundOperationNode constructor to handle " + "events on each edge of the primary input along with the neighborhood taken from the additional inputs.\n" + "\n" + "See \\on_edge for the description of the events delivered." + "\n" + "This class has been introduced in version 0.xx.\n" // @@@ +); + +// --------------------------------------------------------------------------------- +// EdgeProcessor binding + +static db::CompoundRegionOperationNode *new_edge_neighborhood (const std::vector &children, db::EdgeNeighborhoodVisitor *visitor, const db::Coord bext, db::Coord eext, db::Coord din, db::Coord dout) +{ + return new db::EdgeNeighborhoodCompoundOperationNode (children, visitor, bext, eext, din, dout); +} + +gsi::ClassExt decl_CompoundRegionOperationNode_ext ( + gsi::constructor ("new_edge_neighborhood", &new_edge_neighborhood, gsi::arg ("children"), gsi::arg ("visitor"), gsi::arg ("bext", 0), gsi::arg ("eext", 0), gsi::arg ("din", 0), gsi::arg ("dout", 0), + "@brief Creates a new edge neighborhood collector\n" + "\n" + "@param children The inputs to use. The first one in the primary input, the others are neighbors.\n" + "@param visitor The visitor object (see \\EdgeNeighborhoodVisitor) receiving the edge events.\n" + "@param bext The search window extension to use at the edge beginning.\n" + "@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" + ) +); + +} +