mirror of https://github.com/KLayout/klayout.git
WIP: documentation, local merging of polygon for interact, covering ..
This commit is contained in:
parent
aefc3153fe
commit
ae29c75326
|
|
@ -399,7 +399,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
|
||||||
|
|
||||||
db::RegionIterator polygons (begin_merged ());
|
db::RegionIterator polygons (begin_merged ());
|
||||||
|
|
||||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count);
|
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count, true);
|
||||||
|
|
||||||
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
|
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
|
||||||
proc.set_base_verbosity (base_verbosity ());
|
proc.set_base_verbosity (base_verbosity ());
|
||||||
|
|
@ -560,7 +560,7 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
||||||
|
|
||||||
db::RegionIterator polygons (begin_merged ());
|
db::RegionIterator polygons (begin_merged ());
|
||||||
|
|
||||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count);
|
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count, true);
|
||||||
|
|
||||||
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
||||||
proc.set_base_verbosity (base_verbosity ());
|
proc.set_base_verbosity (base_verbosity ());
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,21 @@ CompoundRegionOperationNode::generated_description () const
|
||||||
return std::string ();
|
return std::string ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CompoundRegionOperationNode::is_merged () const
|
||||||
|
{
|
||||||
|
std::vector<db::Region *> iv = inputs ();
|
||||||
|
// NOTE: the primary is supposed to be merged always (except in raw mode)
|
||||||
|
return iv.size () == 1 && (is_subject_regionptr (iv.front ()) || iv.front ()->is_merged ());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CompoundRegionOperationNode::has_external_inputs () const
|
||||||
|
{
|
||||||
|
std::vector<db::Region *> iv = inputs ();
|
||||||
|
return iv.size () == 1 && ! is_subject_regionptr (iv.front ());
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
static void translate (db::Layout *layout, const std::vector<std::unordered_set<db::Polygon> > &in, std::vector<std::unordered_set<db::PolygonRef> > &out)
|
static void translate (db::Layout *layout, const std::vector<std::unordered_set<db::Polygon> > &in, std::vector<std::unordered_set<db::PolygonRef> > &out)
|
||||||
|
|
@ -1052,6 +1067,75 @@ template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_lo
|
||||||
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::Polygon, db::EdgePair> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
|
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::Polygon, db::EdgePair> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
|
||||||
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef, db::EdgePair> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
|
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef, db::EdgePair> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||||
|
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ())
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||||
|
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ())
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
CompoundRegionInteractOperationNode::generated_description () const
|
||||||
|
{
|
||||||
|
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CompoundRegionInteractWithEdgeOperationNode::CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count)
|
||||||
|
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse, min_count, max_count, b->is_merged ())
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
CompoundRegionInteractWithEdgeOperationNode::generated_description () const
|
||||||
|
{
|
||||||
|
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>::generated_description ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CompoundRegionPullOperationNode::CompoundRegionPullOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching)
|
||||||
|
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundRegionPullOperationNode::CompoundRegionPullOperationNode (db::Region *a, db::Region *b, int mode, bool touching)
|
||||||
|
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
CompoundRegionPullOperationNode::generated_description () const
|
||||||
|
{
|
||||||
|
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CompoundRegionPullWithEdgeOperationNode::CompoundRegionPullWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b)
|
||||||
|
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge> (&m_op, a, b), m_op ()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
CompoundRegionPullWithEdgeOperationNode::generated_description () const
|
||||||
|
{
|
||||||
|
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>::generated_description ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
CompoundRegionJoinOperationNode::CompoundRegionJoinOperationNode (const std::vector<CompoundRegionOperationNode *> &inputs)
|
CompoundRegionJoinOperationNode::CompoundRegionJoinOperationNode (const std::vector<CompoundRegionOperationNode *> &inputs)
|
||||||
|
|
@ -1514,17 +1598,8 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
|
||||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode * /*input*/, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode * /*input*/, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||||
: CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
: CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||||
{
|
{
|
||||||
m_has_other = false;
|
m_has_other = other->has_external_inputs ();
|
||||||
std::vector<db::Region *> other_inputs = other->inputs ();
|
m_is_other_merged = other->is_merged ();
|
||||||
if (other_inputs.size () > 1) {
|
|
||||||
m_has_other = true;
|
|
||||||
m_is_other_merged = false; // or do we know better?
|
|
||||||
} else if (other_inputs.size () == 1) {
|
|
||||||
if (! is_subject_regionptr (other_inputs.front ())) {
|
|
||||||
m_has_other = true;
|
|
||||||
m_is_other_merged = other_inputs.front ()->is_merged ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_description ("check");
|
set_description ("check");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,18 @@ public:
|
||||||
*/
|
*/
|
||||||
void set_description (const std::string &d);
|
void set_description (const std::string &d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a value indicating whether the result is definitely merged
|
||||||
|
* The default implementation is based on a heuristic analysis of the inputs.
|
||||||
|
*/
|
||||||
|
virtual bool is_merged () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a value indicating whether this node provides external inputs
|
||||||
|
* A node has external inputs if it has inputs and does not refer to the primary alone.
|
||||||
|
*/
|
||||||
|
virtual bool has_external_inputs () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a value giving a hint how to handle the case of empty intruders
|
* @brief Returns a value giving a hint how to handle the case of empty intruders
|
||||||
*/
|
*/
|
||||||
|
|
@ -676,22 +688,10 @@ class DB_PUBLIC CompoundRegionInteractOperationNode
|
||||||
: public compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>
|
: public compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ())
|
CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ());
|
||||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count)
|
CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ());
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ())
|
std::string generated_description () const;
|
||||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count)
|
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string generated_description () const
|
|
||||||
{
|
|
||||||
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
||||||
{
|
{
|
||||||
|
|
@ -711,16 +711,9 @@ class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode
|
||||||
: public compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>
|
: public compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ())
|
CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ());
|
||||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse, min_count, max_count)
|
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string generated_description () const
|
std::string generated_description () const;
|
||||||
{
|
|
||||||
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>::generated_description ();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
||||||
{
|
{
|
||||||
|
|
@ -740,22 +733,10 @@ class DB_PUBLIC CompoundRegionPullOperationNode
|
||||||
: public compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>
|
: public compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompoundRegionPullOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching)
|
CompoundRegionPullOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching);
|
||||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
CompoundRegionPullOperationNode (db::Region *a, db::Region *b, int mode, bool touching);
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
CompoundRegionPullOperationNode (db::Region *a, db::Region *b, int mode, bool touching)
|
std::string generated_description () const;
|
||||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string generated_description () const
|
|
||||||
{
|
|
||||||
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
||||||
{
|
{
|
||||||
|
|
@ -775,16 +756,9 @@ class DB_PUBLIC CompoundRegionPullWithEdgeOperationNode
|
||||||
: public compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>
|
: public compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompoundRegionPullWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b)
|
CompoundRegionPullWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b);
|
||||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge> (&m_op, a, b), m_op ()
|
|
||||||
{
|
|
||||||
// .. nothing yet ..
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string generated_description () const
|
std::string generated_description () const;
|
||||||
{
|
|
||||||
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>::generated_description ();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t max_vertex_count, double area_ratio) const
|
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t max_vertex_count, double area_ratio) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1534,7 +1534,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
||||||
|
|
||||||
DeepLayer dl_out (polygons.derived ());
|
DeepLayer dl_out (polygons.derived ());
|
||||||
|
|
||||||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count);
|
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count, true);
|
||||||
|
|
||||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||||
proc.set_base_verbosity (base_verbosity ());
|
proc.set_base_verbosity (base_verbosity ());
|
||||||
|
|
@ -1573,7 +1573,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
||||||
|
|
||||||
DeepLayer dl_out (polygons.derived ());
|
DeepLayer dl_out (polygons.derived ());
|
||||||
|
|
||||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count);
|
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true);
|
||||||
|
|
||||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||||
proc.set_base_verbosity (base_verbosity ());
|
proc.set_base_verbosity (base_verbosity ());
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,9 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
|
||||||
|
|
||||||
} else if (! m_other_is_merged && (ids.size () > 1 || ! interactions.intruder_shape (*ids.begin ()).second.is_box ())) {
|
} else if (! m_other_is_merged && (ids.size () > 1 || ! interactions.intruder_shape (*ids.begin ()).second.is_box ())) {
|
||||||
|
|
||||||
|
// NOTE: this local merge is not necessarily giving the same results than a global merge before running
|
||||||
|
// the processor. Reason: the search range is limited, hence not all necessary components may have been
|
||||||
|
// captured.
|
||||||
db::EdgeProcessor ep;
|
db::EdgeProcessor ep;
|
||||||
|
|
||||||
ep.clear ();
|
ep.clear ();
|
||||||
|
|
@ -536,9 +539,31 @@ template class DB_PUBLIC check_local_operation<db::Polygon, db::Polygon>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class PolygonToEdgeProcessor
|
||||||
|
: public db::PolygonSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolygonToEdgeProcessor (db::EdgeProcessor *target, size_t *id)
|
||||||
|
: mp_target (target), mp_id (id)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void put (const db::Polygon &poly)
|
||||||
|
{
|
||||||
|
mp_target->insert (poly, (*mp_id)++);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
db::EdgeProcessor *mp_target;
|
||||||
|
size_t *mp_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template <class TS, class TI, class TR>
|
template <class TS, class TI, class TR>
|
||||||
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged)
|
||||||
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -588,6 +613,24 @@ void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*l
|
||||||
}
|
}
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
|
} else if (! m_other_is_merged && ! (m_min_count == size_t (1) && m_max_count == std::numeric_limits<size_t>::max ())) {
|
||||||
|
|
||||||
|
// in counted mode we need to merge the shapes because they might overlap
|
||||||
|
db::EdgeProcessor ep_merge;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||||
|
for (typename TI::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
|
||||||
|
ep_merge.insert (*e, i);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolygonToEdgeProcessor ps (&ep, &n);
|
||||||
|
db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false);
|
||||||
|
db::SimpleMerge op (1 /*wc>0*/);
|
||||||
|
ep_merge.process (pg, op);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||||
|
|
@ -743,8 +786,8 @@ template class DB_PUBLIC pull_local_operation<db::Polygon, db::Polygon, db::Poly
|
||||||
// ---------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template <class TS, class TI, class TR>
|
template <class TS, class TI, class TR>
|
||||||
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count)
|
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged)
|
||||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -774,10 +817,35 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// locally merge the intruder edges if required
|
||||||
|
std::unordered_set<TI> merged_heap;
|
||||||
|
if (! m_other_is_merged && counting) {
|
||||||
|
|
||||||
|
EdgeBooleanClusterCollector<std::unordered_set<TI> > cluster_collector (&merged_heap, EdgeOr);
|
||||||
|
|
||||||
|
db::box_scanner<TI, size_t> merge_scanner;
|
||||||
|
|
||||||
|
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||||
|
const TI *e = &interactions.intruder_shape (*j).second;
|
||||||
|
if (! e->is_degenerate ()) {
|
||||||
|
merge_scanner.insert (e, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||||
|
|
||||||
|
for (typename std::unordered_set<TI>::const_iterator e = merged_heap.begin (); e != merged_heap.end (); ++e) {
|
||||||
|
scanner.insert2 (e.operator-> (), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
std::list<TR> heap;
|
std::list<TR> heap;
|
||||||
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,7 @@ class interacting_local_operation
|
||||||
: public local_operation<TS, TI, TR>
|
: public local_operation<TS, TI, TR>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count);
|
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||||
|
|
||||||
virtual db::Coord dist () const;
|
virtual db::Coord dist () const;
|
||||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||||
|
|
@ -236,6 +236,7 @@ private:
|
||||||
bool m_touching;
|
bool m_touching;
|
||||||
bool m_inverse;
|
bool m_inverse;
|
||||||
size_t m_min_count, m_max_count;
|
size_t m_min_count, m_max_count;
|
||||||
|
bool m_other_is_merged;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef interacting_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> InteractingLocalOperation;
|
typedef interacting_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> InteractingLocalOperation;
|
||||||
|
|
@ -264,7 +265,7 @@ class interacting_with_edge_local_operation
|
||||||
: public local_operation<TS, TI, TR>
|
: public local_operation<TS, TI, TR>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count);
|
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||||
|
|
||||||
virtual db::Coord dist () const;
|
virtual db::Coord dist () const;
|
||||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||||
|
|
@ -274,6 +275,7 @@ public:
|
||||||
private:
|
private:
|
||||||
bool m_inverse;
|
bool m_inverse;
|
||||||
size_t m_min_count, m_max_count;
|
size_t m_min_count, m_max_count;
|
||||||
|
bool m_other_is_merged;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef interacting_with_edge_local_operation<db::PolygonRef, db::Edge, db::PolygonRef> InteractingWithEdgeLocalOperation;
|
typedef interacting_with_edge_local_operation<db::PolygonRef, db::Edge, db::PolygonRef> InteractingWithEdgeLocalOperation;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,52 @@ module DRC
|
||||||
# out = in.drc((width < 2.0).polygons)
|
# out = in.drc((width < 2.0).polygons)
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
|
# The following global functions are relevant for the DRC expressions:
|
||||||
|
#
|
||||||
|
# @ul
|
||||||
|
# @li \global#angle @/li
|
||||||
|
# @li \global#area @/li
|
||||||
|
# @li \global#bbox_height @/li
|
||||||
|
# @li \global#bbox_max @/li
|
||||||
|
# @li \global#bbox_min @/li
|
||||||
|
# @li \global#bbox_width @/li
|
||||||
|
# @li \global#case @/li
|
||||||
|
# @li \global#corners @/li
|
||||||
|
# @li \global#covering @/li
|
||||||
|
# @li \global#enc @/li
|
||||||
|
# @li \global#enclosing @/li
|
||||||
|
# @li \global#extent_refs @/li
|
||||||
|
# @li \global#extents @/li
|
||||||
|
# @li \global#foreign @/li
|
||||||
|
# @li \global#holes @/li
|
||||||
|
# @li \global#hulls @/li
|
||||||
|
# @li \global#if_all @/li
|
||||||
|
# @li \global#if_any @/li
|
||||||
|
# @li \global#if_none @/li
|
||||||
|
# @li \global#inside @/li
|
||||||
|
# @li \global#interacting @/li
|
||||||
|
# @li \global#iso @/li
|
||||||
|
# @li \global#length @/li
|
||||||
|
# @li \global#middle @/li
|
||||||
|
# @li \global#notch @/li
|
||||||
|
# @li \global#odd_polygons @/li
|
||||||
|
# @li \global#outside @/li
|
||||||
|
# @li \global#overlap @/li
|
||||||
|
# @li \global#overlapping @/li
|
||||||
|
# @li \global#perimeter @/li
|
||||||
|
# @li \global#primary @/li
|
||||||
|
# @li \global#rectangles @/li
|
||||||
|
# @li \global#rectilinear @/li
|
||||||
|
# @li \global#rounded_corners @/li
|
||||||
|
# @li \global#secondary @/li
|
||||||
|
# @li \global#separation @/li
|
||||||
|
# @li \global#sep @/li
|
||||||
|
# @li \global#sized @/li
|
||||||
|
# @li \global#smoothed @/li
|
||||||
|
# @li \global#space @/li
|
||||||
|
# @li \global#width @/li
|
||||||
|
# @/ul
|
||||||
|
#
|
||||||
# The following documentation will list the methods available for DRC expression objects.
|
# The following documentation will list the methods available for DRC expression objects.
|
||||||
|
|
||||||
class DRCOpNode
|
class DRCOpNode
|
||||||
|
|
@ -939,6 +985,34 @@ CODE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
%w(covering overlapping interacting).each do |f|
|
||||||
|
eval <<"CODE"
|
||||||
|
def #{f}(other)
|
||||||
|
@engine._context("#{f}") do
|
||||||
|
other = @engine._make_node(other)
|
||||||
|
if ! other.is_a?(DRCOpNode)
|
||||||
|
raise("Argument " + other.to_s + " to #{f} must be a DRC expression")
|
||||||
|
end
|
||||||
|
DRCOpNodeInteractingWithCount::new(@engine, self, other, :#{f})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CODE
|
||||||
|
end
|
||||||
|
|
||||||
|
%w(inside outside).each do |f|
|
||||||
|
eval <<"CODE"
|
||||||
|
def #{f}(other)
|
||||||
|
@engine._context("#{f}") do
|
||||||
|
other = @engine._make_node(other)
|
||||||
|
if ! other.is_a?(DRCOpNode)
|
||||||
|
raise("Argument " + other.to_s + " to #{f} must be a DRC expression")
|
||||||
|
end
|
||||||
|
DRCOpNodeInteracting::new(@engine, self, other, :#{f})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CODE
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class DRCOpNodeLogicalBool < DRCOpNode
|
class DRCOpNodeLogicalBool < DRCOpNode
|
||||||
|
|
@ -1410,7 +1484,7 @@ class DRCOpNodeInteractingWithCount < DRCOpNodeWithCompare
|
||||||
args = [ self.a.create_node(cache), self.b.create_node(cache), self.inverse ]
|
args = [ self.a.create_node(cache), self.b.create_node(cache), self.inverse ]
|
||||||
args << (self.gt ? self.gt + 1 : (self.ge ? self.ge : 0))
|
args << (self.gt ? self.gt + 1 : (self.ge ? self.ge : 0))
|
||||||
if self.lt || self.le
|
if self.lt || self.le
|
||||||
args << (self.lt ? self.lt : self.le + 1)
|
args << (self.lt ? self.lt - 1 : self.le)
|
||||||
end
|
end
|
||||||
factory = { :covering => :new_enclosing,
|
factory = { :covering => :new_enclosing,
|
||||||
:overlapping => :new_overlapping,
|
:overlapping => :new_overlapping,
|
||||||
|
|
|
||||||
|
|
@ -52,18 +52,143 @@ module DRC
|
||||||
# using measurement operations like "area" on secondary polygons.
|
# using measurement operations like "area" on secondary polygons.
|
||||||
#
|
#
|
||||||
# Here is an example for a generic DRC operation which performs a width
|
# Here is an example for a generic DRC operation which performs a width
|
||||||
# check for less than 0.5.um on the primary shapes.
|
# check for less than 0.5.um on the primary shapes. It uses the \global#width operator:
|
||||||
#
|
#
|
||||||
# @code
|
# @code
|
||||||
# out = in.drc(width < 0.5.um)
|
# out = in.drc(width < 0.5.um)
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
# Another example computes a boolean AND between two layers before selecting
|
# Other single or double-bounded conditions are available too, for example:
|
||||||
# the result polygons with an area larger than 1 square micrometer:
|
|
||||||
#
|
#
|
||||||
# @code
|
# @code
|
||||||
# other = ... another layer ..
|
# out = in.drc(width <= 0.5.um)
|
||||||
# out = in.drc((primary & other).area > 1.0)
|
# out = in.drc(width > 0.5.um)
|
||||||
|
# out = in.drc(width == 0.5.um)
|
||||||
|
# out = in.drc(width != 0.5.um)
|
||||||
|
# out = in.drc(0.2.um < width < 0.5.um)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# To specify the second input for a two-layer check, specify the second input
|
||||||
|
# with the check function. Here a two-layer separation check is used (\global#separation):
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# l1 = input(1, 0)
|
||||||
|
# l2 = input(2, 0)
|
||||||
|
# out = l1.drc(separation(l2) < 0.5.um)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The second input of this check function can be a computed expression. In this
|
||||||
|
# case the local loop will first evaluate the expression for the second input and
|
||||||
|
# then use it inside the check.
|
||||||
|
#
|
||||||
|
# Options for the checks are also specified inside the brackets. For example,
|
||||||
|
# to specify a projection metrics for width use:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(width(projection) < 0.5.um)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The "drc" function supports filter operators. These select input or derived polygons
|
||||||
|
# based on their properties. These filters are:
|
||||||
|
#
|
||||||
|
# @ul
|
||||||
|
# @li "\global#area": select polygons based on their area @/li
|
||||||
|
# @li "\global#perimeter": select polygons based on their perimeter @/li
|
||||||
|
# @li "\global#bbox_min", "\global#bbox_max", "\global#bbox_width", "\global#bbox_height": select polygons based on their bounding box properties @/li
|
||||||
|
# @/ul
|
||||||
|
#
|
||||||
|
# For example, to select polygons with an area larger than one square micrometer, use:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(area > 1.0)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# For the condition, use the usual numerical bounds like:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(area == 1.0)
|
||||||
|
# out = in.drc(area <= 1.0)
|
||||||
|
# out = in.drc(0.2 < area < 1.0)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The result of the area operation is the input polygon if the area condition is met.
|
||||||
|
#
|
||||||
|
# In the same fashion, "perimeter" applies to the perimeter of the polygon.
|
||||||
|
# "bbox_min" etc. will evaluate a particular dimensions of the polygon's bounding box and
|
||||||
|
# use the respective dimension for filtering the polygon.
|
||||||
|
#
|
||||||
|
# Note that it's basically possible to use the polygon filters on any kind of input.
|
||||||
|
# In fact, plain "area" for example is a shortcut for "\global#primary.area" indicating that
|
||||||
|
# the area of primary shapes are supposed to be computed.
|
||||||
|
# However, any input other than the primary is not necessarily complete or it may
|
||||||
|
# consist of multiple polygons. Hence the computed values may be too big or too small.
|
||||||
|
# It's recommended therefore to use the measurement functions on primary polygons
|
||||||
|
# only.
|
||||||
|
#
|
||||||
|
# The "drc" feature also supports some predicates. "predicates" are boolean values
|
||||||
|
# indicating a certain condition. A predicate filter works in a way that it only
|
||||||
|
# passes the polygons
|
||||||
|
# The predicates available currently are:
|
||||||
|
#
|
||||||
|
# @ul
|
||||||
|
# @li "\global#rectangles": Filters rectangles @/li
|
||||||
|
# @li "\global#rectilinear": Filters rectilinear ("Manhattan") polygons @/li
|
||||||
|
# @/ul
|
||||||
|
#
|
||||||
|
# For the same reason as explained above, it's recommended to use these predicates
|
||||||
|
# standalone, so they act on primary shapes. It's possible to use the predicates
|
||||||
|
# on computed shapes or secondary input, but that may not render the desired results.
|
||||||
|
#
|
||||||
|
# The "!" operator will evaluate the expression behind it and return the
|
||||||
|
# current primary shape if the input is empty and return an empty polygon set
|
||||||
|
# if not. Hence the following filter will deliver all polygons which are
|
||||||
|
# not rectangles:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(! rectangles)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The logical "if_any" or "if_all" statements allow connecting multiple
|
||||||
|
# conditions and evaluate to "true" (means: a non-empty shape set) if either
|
||||||
|
# on input is a non-empty shape set ("if_any") or if all inputs are non-empty
|
||||||
|
# ("if_all"). For example, this will select all polygons which are rectangles
|
||||||
|
# and whose area is larger than 20 quare micrometers:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(if_all(rectangles, area > 20.0))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# In fact, "if_all" renders the result of the last expression, provided all
|
||||||
|
# previous ones are non-empty. So this operation will render rectangles
|
||||||
|
# sized by 100 nm and skip all other types of polygons:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(if_all(rectangles, sized(100.nm)))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# Contrary to this, the "if_any" operation will render the first non-empty
|
||||||
|
# expression result and skip the following ones. So this example will
|
||||||
|
# size all rectangles by 100 nm and leave all other types of polygons
|
||||||
|
# untouched:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = in.drc(if_any(rectangles.sized(100.nm), primary))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The "drc" operations feature polygon manipulations where the input is
|
||||||
|
# either the primary polygon or derived shapes.
|
||||||
|
# Manipulations include sizing ("\global#sized"), corner rounding ("\global#rounded_corners"), smoothing ("\global#smoothed")
|
||||||
|
# and boolean operations.
|
||||||
|
#
|
||||||
|
# This example computes a boolean AND between two layers before selecting
|
||||||
|
# the result polygons with an area larger than 1 square micrometer. Note that
|
||||||
|
# "primary" is a placeholder for the primary shape:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# l1 = input(1, 0)
|
||||||
|
# l2 = input(2, 0)
|
||||||
|
# out = l1.drc((primary & l2).area > 1.0)
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
# This example demonstrates how the "drc" operation can improve performance: as the
|
# This example demonstrates how the "drc" operation can improve performance: as the
|
||||||
|
|
@ -71,7 +196,64 @@ module DRC
|
||||||
# less shapes need to be stored hence reducing the memory overhead and CPU time required
|
# less shapes need to be stored hence reducing the memory overhead and CPU time required
|
||||||
# to manage these shapes.
|
# to manage these shapes.
|
||||||
#
|
#
|
||||||
# For more details about the expression see the \DRC# class documentation.
|
# Note that the precise form of the example above is
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = l1.drc((primary & secondary(l2)).area > 1.0)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The "\global#secondar" operator indicates that "l2" is to be used as secondary input to the "drc" function. Only
|
||||||
|
# in this form, the operators of the boolean AND can be reversed:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = l1.drc((secondary(l2) & primary).area > 1.0)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The expression inside the "drc" function is a Ruby object and can be
|
||||||
|
# stored in variables. If you need the same expression multiple times, it can be
|
||||||
|
# more efficient to use the same Ruby object. In this example, the same expression
|
||||||
|
# is used two times. Hence it's computed two times:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# out = l1.drc(((primary & l2).area == 1.0) + ((primary & l2).area == 2.0))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# A more efficient version is:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# overlap_area = (primary & l2).area
|
||||||
|
# out = l1.drc((overlap_area == 1.0) + (overlap_area == 2.0))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# Note that the first line prepares the operation, but does not execute the area computation
|
||||||
|
# or the boolean operation. But when the "drc" function executes the operation it will
|
||||||
|
# only compute the area once as it is represented by the same Ruby object.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The "drc" functionality also offers support for edge pairs and edges. Edge pairs
|
||||||
|
# are the results of check operations and can be turned into polygons using the
|
||||||
|
# "polygons" method:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# drc = in.drc((width < 0.5.um).polygons)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# Similarly, polygons can be converted into edges:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# drc = in.drc(primary.edges)
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# The "drc" framework supports edge vs. edge and edge vs. polygon booleans, edge
|
||||||
|
# filters (\global#length, \global#angle), edge vs. polygon interactions (\global#interacting, \global#overlapping),
|
||||||
|
# edge sampling (\global#start_segments, \global#centers, \global#end_segments) and edge to polygon
|
||||||
|
# conversions (\global#extended, \global#extended_in, \global#extended_out). Edge pairs
|
||||||
|
# can be converted into polygons and edges and separated into first and second edges (\global#first_edges,
|
||||||
|
# \global#second_edges).
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The bottom line is: DRC expressions are quite rich and there is a lot more to be said and written.
|
||||||
|
# More formal details about the bits and pieces can be found in the \DRC# class documentation.
|
||||||
|
|
||||||
def drc(op)
|
def drc(op)
|
||||||
@engine._context("drc") do
|
@engine._context("drc") do
|
||||||
|
|
@ -564,12 +746,8 @@ CODE
|
||||||
# @name covering
|
# @name covering
|
||||||
# @brief Selects shapes entirely covering other shapes
|
# @brief Selects shapes entirely covering other shapes
|
||||||
# @synopsis covering(other) (in conditions)
|
# @synopsis covering(other) (in conditions)
|
||||||
# @synopsis covering(layer, other [, options ])
|
|
||||||
#
|
#
|
||||||
# This function can be used with a layer argument in which case it
|
# This method represents the selector of primary shapes
|
||||||
# is equivalent to "layer.covering" (see \Layer#covering).
|
|
||||||
#
|
|
||||||
# Without a layer argument, this method represents the selector of primary shapes
|
|
||||||
# which entirely cover shapes from the other layer. This version can be put into
|
# which entirely cover shapes from the other layer. This version can be put into
|
||||||
# a condition indicating how many shapes of the other layer need to be covered.
|
# a condition indicating how many shapes of the other layer need to be covered.
|
||||||
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
||||||
|
|
@ -593,32 +771,40 @@ CODE
|
||||||
# @name interacting
|
# @name interacting
|
||||||
# @brief Selects shapes interacting with other shapes
|
# @brief Selects shapes interacting with other shapes
|
||||||
# @synopsis interacting(other) (in conditions)
|
# @synopsis interacting(other) (in conditions)
|
||||||
# @synopsis interacting(layer, other [, options ])
|
|
||||||
#
|
#
|
||||||
# See \covering for a description of the use cases for this function.
|
# See \covering for a description of the use cases for this function.
|
||||||
# When using "interacting", shapes are selected when the interact (overlap, touch)
|
# When using "interacting", shapes are selected when the interact (overlap, touch)
|
||||||
# shapes from the other layer.
|
# shapes from the other layer.
|
||||||
|
#
|
||||||
|
# When using this method with a count, the operation may not render
|
||||||
|
# the correct results if the other input is not merged. By nature of the
|
||||||
|
# generic DRC feature, only those shapes that interact with the primary shape
|
||||||
|
# will be selected. If the other input is split into multiple polygons,
|
||||||
|
# not all components may be captured and the computed interaction count
|
||||||
|
# may be incorrect.
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name overlapping
|
# @name overlapping
|
||||||
# @brief Selects shapes overlapping with other shapes
|
# @brief Selects shapes overlapping with other shapes
|
||||||
# @synopsis overlapping(other) (in conditions)
|
# @synopsis overlapping(other) (in conditions)
|
||||||
# @synopsis overlapping(layer, other [, options ])
|
|
||||||
#
|
#
|
||||||
# See \covering for a description of the use cases for this function.
|
# See \covering for a description of the use cases for this function.
|
||||||
# When using "overlapping", shapes are selected when the overlap
|
# When using "overlapping", shapes are selected when the overlap
|
||||||
# shapes from the other layer.
|
# shapes from the other layer.
|
||||||
|
#
|
||||||
|
# When using this method with a count, the operation may not render
|
||||||
|
# the correct results if the other input is not merged. By nature of the
|
||||||
|
# generic DRC feature, only those shapes that interact with the primary shape
|
||||||
|
# will be selected. If the other input is split into multiple polygons,
|
||||||
|
# not all components may be captured and the computed interaction count
|
||||||
|
# may be incorrect.
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name inside
|
# @name inside
|
||||||
# @brief Selects shapes entirely inside other shapes
|
# @brief Selects shapes entirely inside other shapes
|
||||||
# @synopsis inside(other)
|
# @synopsis inside(other)
|
||||||
# @synopsis inside(layer, other)
|
|
||||||
#
|
#
|
||||||
# This function can be used with a layer argument in which case it
|
# This method represents the selector of primary shapes
|
||||||
# is equivalent to "layer.inside" (see \Layer#inside).
|
|
||||||
#
|
|
||||||
# Without a layer argument, this method represents the selector of primary shapes
|
|
||||||
# which are entirely inside shapes from the other layer.
|
# which are entirely inside shapes from the other layer.
|
||||||
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
||||||
|
|
||||||
|
|
@ -626,12 +812,8 @@ CODE
|
||||||
# @name outside
|
# @name outside
|
||||||
# @brief Selects shapes entirely outside other shapes
|
# @brief Selects shapes entirely outside other shapes
|
||||||
# @synopsis outside(other)
|
# @synopsis outside(other)
|
||||||
# @synopsis outside(layer, other)
|
|
||||||
#
|
#
|
||||||
# This function can be used with a layer argument in which case it
|
# This method represents the selector of primary shapes
|
||||||
# is equivalent to "layer.outside" (see \Layer#outside).
|
|
||||||
#
|
|
||||||
# Without a layer argument, this method represents the selector of primary shapes
|
|
||||||
# which are entirely outside shapes from the other layer.
|
# which are entirely outside shapes from the other layer.
|
||||||
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
||||||
|
|
||||||
|
|
@ -642,9 +824,8 @@ CODE
|
||||||
outside
|
outside
|
||||||
overlapping
|
overlapping
|
||||||
).each do |f|
|
).each do |f|
|
||||||
# NOTE: these methods are fallback for the respective global ones which route to DRCLayer or here.
|
|
||||||
eval <<"CODE"
|
eval <<"CODE"
|
||||||
def _cop_#{f}(other)
|
def #{f}(other)
|
||||||
primary.#{f}(other)
|
primary.#{f}(other)
|
||||||
end
|
end
|
||||||
CODE
|
CODE
|
||||||
|
|
@ -674,6 +855,7 @@ CODE
|
||||||
# out = in.drc(enclosing(other) > 0.2.um)
|
# out = in.drc(enclosing(other) > 0.2.um)
|
||||||
# out = in.drc(enclosing(other) >= 0.2.um)
|
# out = in.drc(enclosing(other) >= 0.2.um)
|
||||||
# out = in.drc(enclosing(other) == 0.2.um)
|
# out = in.drc(enclosing(other) == 0.2.um)
|
||||||
|
# out = in.drc(enclosing(other) != 0.2.um)
|
||||||
# out = in.drc(0.1.um <= enclosing(other) < 0.2.um)
|
# out = in.drc(0.1.um <= enclosing(other) < 0.2.um)
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
|
|
@ -728,6 +910,7 @@ CODE
|
||||||
# out = in.drc(width > 0.2.um)
|
# out = in.drc(width > 0.2.um)
|
||||||
# out = in.drc(width >= 0.2.um)
|
# out = in.drc(width >= 0.2.um)
|
||||||
# out = in.drc(width == 0.2.um)
|
# out = in.drc(width == 0.2.um)
|
||||||
|
# out = in.drc(width != 0.2.um)
|
||||||
# out = in.drc(0.1.um <= width < 0.2.um)
|
# out = in.drc(0.1.um <= width < 0.2.um)
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -1579,7 +1579,6 @@ CODE
|
||||||
bbox
|
bbox
|
||||||
centers
|
centers
|
||||||
corners
|
corners
|
||||||
covering
|
|
||||||
end_segments
|
end_segments
|
||||||
extended
|
extended
|
||||||
extended_in
|
extended_in
|
||||||
|
|
@ -1591,9 +1590,7 @@ CODE
|
||||||
holes
|
holes
|
||||||
hulls
|
hulls
|
||||||
in
|
in
|
||||||
inside
|
|
||||||
inside_part
|
inside_part
|
||||||
interacting
|
|
||||||
intersections
|
intersections
|
||||||
iso
|
iso
|
||||||
isolated
|
isolated
|
||||||
|
|
@ -1619,9 +1616,7 @@ CODE
|
||||||
ongrid
|
ongrid
|
||||||
or
|
or
|
||||||
output
|
output
|
||||||
outside
|
|
||||||
outside_part
|
outside_part
|
||||||
overlapping
|
|
||||||
perimeter
|
perimeter
|
||||||
pull_inside
|
pull_inside
|
||||||
pull_interacting
|
pull_interacting
|
||||||
|
|
|
||||||
|
|
@ -188,3 +188,13 @@ TEST(12d)
|
||||||
{
|
{
|
||||||
run_test (_this, "12", true);
|
run_test (_this, "12", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(13)
|
||||||
|
{
|
||||||
|
run_test (_this, "13", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(13d)
|
||||||
|
{
|
||||||
|
run_test (_this, "13", true);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,52 @@ renders edge pairs. To obtain polygons from these edge pairs, use the "polygons"
|
||||||
out = in.drc((width < 2.0).polygons)
|
out = in.drc((width < 2.0).polygons)
|
||||||
</pre>
|
</pre>
|
||||||
</p><p>
|
</p><p>
|
||||||
|
The following global functions are relevant for the DRC expressions:
|
||||||
|
</p><p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#case">global#case</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#secondary">global#secondary</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#primary">global#primary</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#foreign">global#foreign</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#if_all">global#if_all</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#if_any">global#if_any</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#if_none">global#if_none</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#bbox_height">global#bbox_height</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#bbox_width">global#bbox_width</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#bbox_max">global#bbox_max</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#bbox_min">global#bbox_min</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#area">global#area</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#hulls">global#hulls</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#holes">global#holes</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#odd_polygons">global#odd_polygons</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#perimeter">global#perimeter</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#rectangles">global#rectangles</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#rectilinear">global#rectilinear</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#length">global#length</a> (in condition) </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#angle">global#angle</a> (in condition) </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#corners">global#corners</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#extent_refs">global#extent_refs</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#extents">global#extents</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#middle">global#middle</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#rounded_corners">global#rounded_corners</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#sized">global#sized</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#smoothed">global#smoothed</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#covering">global#covering</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#interacting">global#interacting</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#overlapping">global#overlapping</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#inside">global#inside</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#outside">global#outside</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#enclosing">global#enclosing</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#separation">global#separation</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#overlap">global#overlap</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#width">global#width</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#space">global#space</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#notch">global#notch</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#iso">global#iso</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#sep">global#sep</a> </li>
|
||||||
|
<li><a href="/about/drc_ref_global.xml#enc">global#enc</a> </li>
|
||||||
|
</ul>
|
||||||
|
</p><p>
|
||||||
The following documentation will list the methods available for DRC expression objects.
|
The following documentation will list the methods available for DRC expression objects.
|
||||||
</p>
|
</p>
|
||||||
<h2-index/>
|
<h2-index/>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
source $drc_test_source
|
||||||
|
target $drc_test_target
|
||||||
|
|
||||||
|
if $drc_test_deep
|
||||||
|
deep
|
||||||
|
end
|
||||||
|
|
||||||
|
l1 = input(1, 0)
|
||||||
|
l2 = input(2, 0)
|
||||||
|
l3 = input(3, 0)
|
||||||
|
|
||||||
|
l1.output(1, 0)
|
||||||
|
l2.output(2, 0)
|
||||||
|
l3.output(3, 0)
|
||||||
|
|
||||||
|
l2.drc(covering(l1)).output(100, 0)
|
||||||
|
l2.drc(! covering(l1)).output(101, 0)
|
||||||
|
|
||||||
|
l1.drc(interacting(l2)).output(110, 0)
|
||||||
|
l1.drc(! interacting(l2)).output(111, 0)
|
||||||
|
l1.drc(interacting(l2) >= 2).output(112, 0)
|
||||||
|
l1.drc(interacting(l2) < 2).output(113, 0)
|
||||||
|
|
||||||
|
l1.drc(overlapping(l2)).output(120, 0)
|
||||||
|
l1.drc(! overlapping(l2)).output(121, 0)
|
||||||
|
l1.drc(overlapping(l2) >= 2).output(122, 0)
|
||||||
|
l1.drc(overlapping(l2) < 2).output(123, 0)
|
||||||
|
|
||||||
|
l1.drc(outside(l2)).output(130, 0)
|
||||||
|
l1.drc(! outside(l2)).output(131, 0)
|
||||||
|
|
||||||
|
l1.drc(inside(l2)).output(140, 0)
|
||||||
|
l1.drc(! inside(l2)).output(141, 0)
|
||||||
|
|
||||||
|
l2e = secondary(l2).edges
|
||||||
|
l1e = primary.edges
|
||||||
|
|
||||||
|
# Secondary edges are supported, but as secondaries are not merged
|
||||||
|
# internally, the result is not well defined for unmerged secondary:
|
||||||
|
|
||||||
|
l1.drc(interacting(l2e)).output(200, 0)
|
||||||
|
l1.drc(! interacting(l2e)).output(201, 0)
|
||||||
|
l1.drc(interacting(l2e) >= 4).output(202, 0)
|
||||||
|
l1.drc(interacting(l2e) < 4).output(203, 0)
|
||||||
|
|
||||||
|
# TODO: edge-to-polygon interactions and edge-to-edge interactions not supported yet
|
||||||
|
|
||||||
|
# l1.drc(l1e.interacting(l2)).output(210, 0)
|
||||||
|
# l1.drc(! l1e.interacting(l2)).output(211, 0)
|
||||||
|
# l1.drc(l1e.interacting(l2) >= 2).output(212, 0)
|
||||||
|
# l1.drc(l1e.interacting(l2) < 2).output(213, 0)
|
||||||
|
|
||||||
|
# l1.drc(l1e.interacting(l2e)).output(210, 0)
|
||||||
|
# l1.drc(! l1e.interacting(l2e)).output(211, 0)
|
||||||
|
# l1.drc(l1e.interacting(l2e) >= 2).output(212, 0)
|
||||||
|
# l1.drc(l1e.interacting(l2e) < 2).output(213, 0)
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue