diff --git a/src/db/db/dbEdgeNeighborhood.cc b/src/db/db/dbEdgeNeighborhood.cc index 5ec532654..c171d04ae 100644 --- a/src/db/db/dbEdgeNeighborhood.cc +++ b/src/db/db/dbEdgeNeighborhood.cc @@ -195,7 +195,9 @@ EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperation 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 (); } void @@ -223,7 +225,9 @@ EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperation scanner.insert1 (&edges.back (), ie); } + const_cast (mp_visitor.get ())->begin_polygon (layout, cell, pr); do_collect_neighbors (scanner, layout, cell); + const_cast (mp_visitor.get ())->end_polygon (); } } diff --git a/src/db/db/dbEdgeNeighborhood.h b/src/db/db/dbEdgeNeighborhood.h index 6f2913e94..b01295d18 100644 --- a/src/db/db/dbEdgeNeighborhood.h +++ b/src/db/db/dbEdgeNeighborhood.h @@ -55,6 +55,18 @@ public: */ virtual ~EdgeNeighborhoodVisitor () { } + /** + * @brief Event handler called when a new polygon is encountered + * Following this event, the edges with their neighborhood are reported. + * After the edges are reported, "end_polygon" is called. + */ + virtual void begin_polygon (const db::Layout * /*layout*/, const db::Cell * /*cell*/, const db::Polygon & /*polygon*/) { } + + /** + * @brief Event handler called after the polygon was processed + */ + virtual void end_polygon () { } + /** * @brief Event handler for each edge plus it's neighborhood */ diff --git a/src/db/db/gsiDeclDbEdgeNeighborhood.cc b/src/db/db/gsiDeclDbEdgeNeighborhood.cc index 128721a00..1cbed771e 100644 --- a/src/db/db/gsiDeclDbEdgeNeighborhood.cc +++ b/src/db/db/gsiDeclDbEdgeNeighborhood.cc @@ -59,6 +59,38 @@ public: gsi::Callback f_on_edge; + void issue_begin_polygon (const db::Layout *, const db::Cell *, const db::Polygon &poly) + { + // just for signature + } + + void begin_polygon (const db::Layout *layout, const db::Cell *cell, const db::Polygon &poly) + { + if (f_begin_polygon.can_issue ()) { + // NOTE: as scripts are potentially thread unsafe, we lock here + tl::MutexLocker locker (&m_lock); + return f_begin_polygon.issue (&EdgeNeighborhoodVisitorImpl::begin_polygon, layout, cell, poly); + } + } + + gsi::Callback f_begin_polygon; + + void issue_end_polygon () + { + // just for signature + } + + void end_polygon () + { + if (f_end_polygon.can_issue ()) { + // NOTE: as scripts are potentially thread unsafe, we lock here + tl::MutexLocker locker (&m_lock); + return f_end_polygon.issue (&EdgeNeighborhoodVisitorImpl::end_polygon); + } + } + + gsi::Callback f_end_polygon; + static tl::Variant build_neighbors (const db::EdgeNeighborhoodVisitor::neighbors_type &neighbors) { tl::Variant result; @@ -127,6 +159,15 @@ Class decl_EdgeNeighborhoodVisitorImpl (decl_E "goes from (0,0) to (length,0).\n" "\n" "The polygons are boxes for manhattan input and trapezoids in the general case.\n" + ) + + gsi::callback ("begin_polygon", &EdgeNeighborhoodVisitorImpl::issue_begin_polygon, &EdgeNeighborhoodVisitorImpl::f_begin_polygon, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("polygon"), + "@brief Is called for each new polygon\n" + "This event announces a new primary polygon. After this event, the edges of the polygon are reported via \\on_edge, " + "followed by a call of \\end_polygon." + ) + + 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." ), "@brief A visitor for the neighborhood of edges in the input\n" "\n"