Generalization: providing output functionality.

This commit is contained in:
Matthias Koefferlein 2024-10-31 21:34:17 +01:00
parent 9f2a2075c7
commit 0cca9afc7e
3 changed files with 245 additions and 38 deletions

View File

@ -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<db::Polygon> *polygons) const
{
disconnect_outputs ();
mp_polygons = polygons;
}
void
EdgeNeighborhoodVisitor::connect_output (db::Layout *layout, std::unordered_set<db::PolygonRef> *polygons) const
{
disconnect_outputs ();
mp_layout = layout;
mp_polygon_refs = polygons;
}
void
EdgeNeighborhoodVisitor::connect_output (db::Layout * /*layout*/, std::unordered_set<db::Edge> *edges) const
{
disconnect_outputs ();
mp_edges = edges;
}
void
EdgeNeighborhoodVisitor::connect_output (Layout * /*layout*/, std::unordered_set<db::EdgePair> *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<CompoundRegionOperationNode *> &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<db
void
EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, const db::LocalProcessorBase *proc) const
{
compute_local_impl<db::PolygonRef> (cache, layout, cell, interactions, results, proc);
compute_local_impl<db::PolygonRef, db::Edge> (cache, layout, cell, interactions, results, proc);
}
void
EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Edge> > &results, const db::LocalProcessorBase *proc) const
{
compute_local_impl<db::Polygon> (cache, layout, cell, interactions, results, proc);
compute_local_impl<db::Polygon, db::Edge> (cache, layout, cell, interactions, results, proc);
}
template <class T>
void
EdgeNeighborhoodCompoundOperationNode::compute_local_impl (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<db::Edge> > & /*results*/, const db::LocalProcessorBase *proc) const
EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, const db::LocalProcessorBase *proc) const
{
compute_local_impl<db::Polygon, db::Polygon> (cache, layout, cell, interactions, results, proc);
}
void
EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, const db::LocalProcessorBase *proc) const
{
compute_local_impl<db::Polygon, db::EdgePair> (cache, layout, cell, interactions, results, proc);
}
void
EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, const db::LocalProcessorBase *proc) const
{
compute_local_impl<db::PolygonRef, db::PolygonRef> (cache, layout, cell, interactions, results, proc);
}
void
EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, const db::LocalProcessorBase *proc) const
{
compute_local_impl<db::PolygonRef, db::EdgePair> (cache, layout, cell, interactions, results, proc);
}
template <class T, class TR>
void
EdgeNeighborhoodCompoundOperationNode::compute_local_impl (CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<TR> > &results, const db::LocalProcessorBase *proc) const
{
if (! mp_visitor) {
return;
}
tl_assert (interactions.num_subjects () == 1);
tl_assert (! results.empty ());
db::box_scanner2<db::Edge, unsigned int, db::Polygon, unsigned int> scanner;
try {
std::list<db::Edge> edges;
std::list<db::Polygon> polygons;
mp_visitor->connect_output (layout, &results.front ());
for (unsigned int i = 0; i < children (); ++i) {
db::box_scanner2<db::Edge, unsigned int, db::Polygon, unsigned int> scanner;
std::vector<std::unordered_set<T> > others;
others.push_back (std::unordered_set<T> ());
std::list<db::Edge> edges;
std::list<db::Polygon> polygons;
shape_interactions<T, T> 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<std::unordered_set<T> > others;
others.push_back (std::unordered_set<T> ());
shape_interactions<T, T> 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<db::EdgeNeighborhoodVisitor *> (mp_visitor.get ())->begin_polygon (layout, cell, pr.instantiate ());
do_collect_neighbors (scanner, layout, cell);
const_cast<db::EdgeNeighborhoodVisitor *> (mp_visitor.get ())->end_polygon ();
const_cast<db::EdgeNeighborhoodVisitor *> (mp_visitor.get ())->begin_polygon (layout, cell, pr.instantiate ());
do_collect_neighbors (scanner, layout, cell);
const_cast<db::EdgeNeighborhoodVisitor *> (mp_visitor.get ())->end_polygon ();
mp_visitor->disconnect_outputs ();
} catch (...) {
mp_visitor->disconnect_outputs ();
throw;
}
}
}

View File

@ -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<db::Polygon> *polygons) const;
/**
* @brief Configure the polygon ref output
*/
void connect_output (db::Layout *layout, std::unordered_set<db::PolygonRef> *polygons) const;
/**
* @brief Configure the edge output
*/
void connect_output (db::Layout * /*layout*/, std::unordered_set<db::Edge> *edges) const;
/**
* @brief Configure the edge pair output
*/
void connect_output (db::Layout * /*layout*/, std::unordered_set<db::EdgePair> *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<db::Polygon> *mp_polygons;
mutable std::unordered_set<db::PolygonRef> *mp_polygon_refs;
mutable std::unordered_set<db::Edge> *mp_edges;
mutable std::unordered_set<db::EdgePair> *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<db::Polygon, db::Polygon> & /*interactions*/, std::vector<std::unordered_set<db::Edge> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::Edge> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
// not implemented
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::Polygon, db::Polygon> & /*interactions*/, std::vector<std::unordered_set<db::Polygon> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { }
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::Polygon, db::Polygon> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { }
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::PolygonRef> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { }
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { }
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::Polygon, db::Polygon> & /*interactions*/, std::vector<std::unordered_set<db::Polygon> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::Polygon, db::Polygon> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::PolygonRef> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
virtual void do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*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<db::Edge, unsigned int, db::Polygon, unsigned int> &scanner, const db::Layout *layout, const db::Cell *cell) const;
template <class T>
void compute_local_impl (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<T, T> & /*interactions*/, std::vector<std::unordered_set<db::Edge> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
template <class T, class TR>
void compute_local_impl (CompoundRegionOperationCache * /*cache*/, db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<T, T> & /*interactions*/, std::vector<std::unordered_set<TR> > & /*results*/, const db::LocalProcessorBase * /*proc*/) const;
};
}

View File

@ -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<gsi::EdgeNeighborhoodVisitorImpl> 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<gsi::EdgeNeighborhoodVisitorImpl> 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<gsi::EdgeNeighborhoodVisitorImpl> 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<db::CompoundRegionOperationNode> 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"
)
);