Merge pull request #749 from KLayout/verification-enhancements
Numerous verification enhancements
|
|
@ -378,28 +378,77 @@ AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &f
|
|||
return new_edge_pairs.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
namespace {
|
||||
|
||||
class OutputPairHolder
|
||||
{
|
||||
public:
|
||||
OutputPairHolder (InteractingOutputMode output_mode, bool merged_semantics)
|
||||
{
|
||||
if (output_mode == None) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (output_mode == Positive || output_mode == Negative || output_mode == PositiveAndNegative) {
|
||||
m_positive.reset (new FlatRegion (merged_semantics));
|
||||
m_results.push_back (& m_positive->raw_polygons ());
|
||||
} else {
|
||||
m_results.push_back ((db::Shapes *) 0);
|
||||
}
|
||||
|
||||
if (output_mode == PositiveAndNegative) {
|
||||
m_negative.reset (new FlatRegion (merged_semantics));
|
||||
m_results.push_back (& m_negative->raw_polygons ());
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *> region_pair ()
|
||||
{
|
||||
return std::make_pair (m_positive.release (), m_negative.release ());
|
||||
}
|
||||
|
||||
const std::vector<db::Shapes *> &results () { return m_results; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<FlatRegion> m_positive, m_negative;
|
||||
std::vector<db::Shapes *> m_results;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
OutputPairHolder oph (output_mode, merged_semantics ());
|
||||
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return clone ();
|
||||
return std::make_pair (clone (), clone ());
|
||||
}
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new EmptyRegion (), clone ());
|
||||
}
|
||||
} else if (empty ()) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count, true);
|
||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -413,71 +462,42 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
|
|||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
return output.release ();
|
||||
|
||||
#else
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
|
||||
ResultCountingInserter inserter (counted_results);
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (count ());
|
||||
scanner.reserve2 (other.count ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
region_to_edge_interaction_filter<db::Polygon, db::Edge, ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
if (inverse) {
|
||||
inserter.init (p.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery e (counting ? other.addressable_merged_edges () : other.addressable_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
|
||||
// select hits based on their count
|
||||
|
||||
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= min_count && r->second <= max_count;
|
||||
if (hit != inverse) {
|
||||
output->insert (*r->first);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
#endif
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
OutputPairHolder oph (output_mode, merged_semantics ());
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
} else {
|
||||
return clone ();
|
||||
}
|
||||
} else if (empty ()) {
|
||||
return clone ();
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (clone (), clone ());
|
||||
}
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new EmptyRegion (), clone ());
|
||||
}
|
||||
}
|
||||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_with_text_local_operation<db::Polygon, db::Text, db::Polygon> op (inverse, min_count, max_count);
|
||||
db::interacting_with_text_local_operation<db::Polygon, db::Text, db::Polygon> op (output_mode, min_count, max_count);
|
||||
|
||||
db::local_processor<db::Polygon, db::Text, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -487,84 +507,58 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse,
|
|||
std::vector<generic_shape_iterator<db::Text> > others;
|
||||
others.push_back (other.begin ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
|
||||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
|
||||
return output.release ();
|
||||
|
||||
#else
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
|
||||
ResultCountingInserter inserter (counted_results);
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Text, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (count ());
|
||||
scanner.reserve2 (other.count ());
|
||||
|
||||
region_to_text_interaction_filter<db::Polygon, db::Text, ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
if (inverse) {
|
||||
inserter.init (p.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
AddressableTextDelivery e (other.addressable_texts ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Text> ());
|
||||
|
||||
// select hits based on their count
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (true));
|
||||
|
||||
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= min_count && r->second <= max_count;
|
||||
if (hit != inverse) {
|
||||
output->insert (*r->first);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
#endif
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
OutputPairHolder oph (output_mode, merged_semantics ());
|
||||
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
return clone ();
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (clone (), clone ());
|
||||
}
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
// clear, if b is empty and
|
||||
// * mode is inside, enclosing or interacting and inverse is false ("inside" or "interacting")
|
||||
// * mode is outside and inverse is true ("not outside")
|
||||
if ((mode <= 0) != inverse) {
|
||||
return new EmptyRegion ();
|
||||
if ((mode <= 0)) {
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new EmptyRegion (), clone ());
|
||||
}
|
||||
} else {
|
||||
return clone ();
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (clone(), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (clone (), new EmptyRegion ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count, true);
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -574,121 +568,9 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
|
||||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
|
||||
return output.release ();
|
||||
|
||||
#else
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
size_t n = 0;
|
||||
size_t nstart = 0;
|
||||
|
||||
if (mode < -1) {
|
||||
|
||||
// in enclosing mode self must be primary and other the secondary. For other
|
||||
// modes it's the other way round
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
nstart = n;
|
||||
|
||||
}
|
||||
|
||||
if (min_count == size_t (1) && max_count == std::numeric_limits<size_t>::max ()) {
|
||||
|
||||
if (mode < 0) {
|
||||
|
||||
// NOTE: on "inside" or "enclosing", the other region must be merged
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (RegionIterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
++n;
|
||||
|
||||
} else {
|
||||
|
||||
// with counting we need to separate the other polygons by different properties
|
||||
|
||||
// cannot only have min_count/max_count in outside mode
|
||||
tl_assert (mode <= 0);
|
||||
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
++n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mode >= -1) {
|
||||
|
||||
nstart = n;
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// there should be at least one element to look at for primary
|
||||
tl_assert (nstart > 0);
|
||||
|
||||
db::InteractionDetector id (mode, nstart - 1);
|
||||
id.set_include_touching (touching);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
|
||||
std::map <size_t, size_t> interaction_counts;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () ; ++i) {
|
||||
if (i->first < nstart && i->second >= nstart) {
|
||||
interaction_counts [mode < -1 ? i->first : i->second] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
output->reserve (n);
|
||||
|
||||
n = (mode < -1 ? 0 : nstart);
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
size_t count = 0;
|
||||
std::map <size_t, size_t>::const_iterator c = interaction_counts.find (n);
|
||||
if (c != interaction_counts.end ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= min_count && count <= max_count) != inverse) {
|
||||
output->insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
#endif
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
|
|
|
|||
|
|
@ -139,72 +139,107 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, false);
|
||||
return selected_interacting_generic (other, 1, false, Positive, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, true);
|
||||
return selected_interacting_generic (other, 1, false, Negative, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, PositiveAndNegative, size_t (0), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, false);
|
||||
return selected_interacting_generic (other, -1, true, Positive, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, true);
|
||||
return selected_interacting_generic (other, -1, true, Negative, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, PositiveAndNegative, size_t (0), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, -2, false, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, -2, false, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, -2, false, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, -2, false, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, -2, false, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, true, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, true, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, false, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, false, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const
|
||||
|
|
@ -245,9 +280,9 @@ protected:
|
|||
|
||||
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual TextsDelegate *pull_generic (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -1060,13 +1060,13 @@ template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_lo
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
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 ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, 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 ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1080,7 +1080,7 @@ CompoundRegionInteractOperationNode::generated_description () const
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
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 ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -753,7 +753,8 @@ public:
|
|||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { }
|
||||
|
||||
private:
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> m_op;
|
||||
typedef db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op_type;
|
||||
op_type m_op;
|
||||
};
|
||||
|
||||
class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode
|
||||
|
|
|
|||
|
|
@ -1519,9 +1519,67 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
namespace
|
||||
{
|
||||
|
||||
class InteractingResultHolder
|
||||
{
|
||||
public:
|
||||
InteractingResultHolder (InteractingOutputMode output_mode, bool is_merged, const db::DeepLayer &polygons)
|
||||
: m_output_mode (output_mode), m_is_merged (is_merged)
|
||||
{
|
||||
if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
m_dl1 = db::DeepLayer (polygons.derived ());
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
m_dl1 = db::DeepLayer (polygons.derived ());
|
||||
m_dl2 = db::DeepLayer (polygons.derived ());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned int> layers () const
|
||||
{
|
||||
std::vector<unsigned int> l;
|
||||
if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
l.push_back (m_dl1.layer ());
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
l.push_back (m_dl1.layer ());
|
||||
l.push_back (m_dl2.layer ());
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *> result_pair ()
|
||||
{
|
||||
if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
db::DeepRegion *res = new db::DeepRegion (m_dl1);
|
||||
res->set_is_merged (m_is_merged);
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (res, 0);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
db::DeepRegion *res1 = new db::DeepRegion (m_dl1);
|
||||
res1->set_is_merged (m_is_merged);
|
||||
db::DeepRegion *res2 = new db::DeepRegion (m_dl2);
|
||||
res2->set_is_merged (m_is_merged);
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (res1, res2);
|
||||
} else {
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
InteractingOutputMode m_output_mode;
|
||||
bool m_is_merged;
|
||||
DeepLayer m_dl1, m_dl2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
if (output_mode == None) {
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (0, 0);
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
|
|
@ -1539,9 +1597,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
// NOTE: on "inside" or with counting, the other polygons must be merged
|
||||
const db::DeepLayer &other_polygons = (mode < 0 || counting) ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count, true);
|
||||
db::InteractingLocalOperation op (mode, touching, output_mode, 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 ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -1553,17 +1609,16 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ());
|
||||
bool result_is_merged = (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
|
|
@ -1580,9 +1635,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true);
|
||||
db::InteractingWithEdgeLocalOperation op (output_mode, 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 ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -1594,13 +1647,12 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
bool result_is_merged = (! split_after && other.is_merged () && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (other.is_merged () && (merged_semantics () || is_merged ()));
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -1706,8 +1758,9 @@ DeepRegion::pull_generic (const Texts &other) const
|
|||
return res;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
|
@ -1722,9 +1775,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
|
|||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithTextLocalOperation op (inverse, min_count, max_count);
|
||||
db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, 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_description (progress_desc ());
|
||||
|
|
@ -1736,13 +1787,12 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (merged_semantics () || is_merged ());
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,9 +140,9 @@ protected:
|
|||
|
||||
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual TextsDelegate *pull_generic (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ public:
|
|||
DeviceParameterCompareDelegate () { }
|
||||
virtual ~DeviceParameterCompareDelegate () { }
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const = 0;
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const = 0;
|
||||
virtual bool equal (const db::Device &a, const db::Device &b) const = 0;
|
||||
};
|
||||
|
|
@ -273,6 +274,11 @@ public:
|
|||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
virtual bool equal (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const
|
||||
{
|
||||
return new EqualDeviceParameters (*this);
|
||||
}
|
||||
|
||||
EqualDeviceParameters &operator+= (const EqualDeviceParameters &other);
|
||||
|
||||
EqualDeviceParameters operator+ (const EqualDeviceParameters &other) const
|
||||
|
|
@ -298,6 +304,11 @@ public:
|
|||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
virtual bool equal (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const
|
||||
{
|
||||
return new AllDeviceParametersAreEqual (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_relative;
|
||||
};
|
||||
|
|
@ -574,6 +585,14 @@ public:
|
|||
/**
|
||||
* @brief Gets the parameter compare delegate or null if no such delegate is registered
|
||||
*/
|
||||
const db::DeviceParameterCompareDelegate *parameter_compare_delegate () const
|
||||
{
|
||||
return mp_pc_delegate.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter compare delegate or null if no such delegate is registered (non-const version)
|
||||
*/
|
||||
db::DeviceParameterCompareDelegate *parameter_compare_delegate ()
|
||||
{
|
||||
return mp_pc_delegate.get ();
|
||||
|
|
|
|||
|
|
@ -108,18 +108,25 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_outside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_outside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
|
|
|
|||
|
|
@ -1280,6 +1280,14 @@ void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned
|
|||
run (op, subject_layer, il, ol);
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector<unsigned int> &output_layers)
|
||||
{
|
||||
std::vector<unsigned int> ol, il;
|
||||
il.push_back (intruder_layer);
|
||||
run (op, subject_layer, il, output_layers);
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ public:
|
|||
local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set<db::cell_index_type> *breakout_cells = 0);
|
||||
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector<unsigned int> &output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, const std::vector<unsigned int> &output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer);
|
||||
void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers) const;
|
||||
|
|
|
|||
|
|
@ -1671,7 +1671,9 @@ Layout::do_update ()
|
|||
// HINT: because of some gcc bug, automatic destruction of the tl::Progress
|
||||
// object does not work. We overcome this problem by creating the object with new
|
||||
// and catching exceptions.
|
||||
tl::RelativeProgress *pr = new tl::RelativeProgress (tl::to_string (tr ("Sorting layout")), m_cells_size, 1000);
|
||||
// As this operation is critical we don't want to have it cancelled. Plus: do_update is called during ~LayoutLocker and
|
||||
// if we throw exceptions then, we'll get a runtime assertion.
|
||||
tl::RelativeProgress *pr = new tl::RelativeProgress (tl::to_string (tr ("Sorting layout")), m_cells_size, 0, false /*can't cancel*/);
|
||||
pr->set_desc ("");
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -632,6 +632,9 @@ LayoutToNetlistStandardReader::read_pin (db::Netlist * /*netlist*/, db::LayoutTo
|
|||
}
|
||||
|
||||
size_t pin_id = circuit->add_pin (pin).id ();
|
||||
// NOTE: because we identify pins by their order and not by ID we need to ensure the pin IDs are
|
||||
// generated sequentially.
|
||||
tl_assert (circuit->pin_count () == pin_id + 1);
|
||||
if (net) {
|
||||
circuit->connect_pin (pin_id, net);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -561,7 +561,8 @@ void std_writer_impl<Keys>::write (const db::SubCircuit &subcircuit, std::map<co
|
|||
*mp_stream << indent << indent2 << Keys::property_key << "(" << p->first.to_parsable_string () << " " << p->second.to_parsable_string () << ")" << endl;
|
||||
}
|
||||
|
||||
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
|
||||
unsigned int pin_id = 0;
|
||||
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p, ++pin_id) {
|
||||
const db::Net *net = subcircuit.net_for_pin (p->id ());
|
||||
if (net) {
|
||||
if (separate_lines) {
|
||||
|
|
@ -569,7 +570,7 @@ void std_writer_impl<Keys>::write (const db::SubCircuit &subcircuit, std::map<co
|
|||
} else {
|
||||
*mp_stream << " ";
|
||||
}
|
||||
*mp_stream << Keys::pin_key << "(" << tl::to_string (p->id ()) << " " << net2id [net] << ")";
|
||||
*mp_stream << Keys::pin_key << "(" << tl::to_string (pin_id) << " " << net2id [net] << ")";
|
||||
if (separate_lines) {
|
||||
*mp_stream << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,19 +88,19 @@ namespace db
|
|||
*
|
||||
* [xref-def]:
|
||||
*
|
||||
* circuit([non] [non] [status]? [circuit-xrefs])
|
||||
* circuit([non] [non] [status]? [message]? [circuit-xrefs])
|
||||
* - circuit pair [short key: X]
|
||||
*
|
||||
* [circuit-xrefs]:
|
||||
*
|
||||
* xref([pair]*)
|
||||
* xref([pair]*) - circuit cross-reference part [short key: Z]
|
||||
*
|
||||
* [pair]
|
||||
*
|
||||
* pin([ion] [ion] [status]?) - a pin pair [short key: P]
|
||||
* device([ion] [ion] [status]?) - a device pair [short key: D]
|
||||
* circuit([ion] [ion] [status]?) - a subcircuit pair [short key: X]
|
||||
* net([ion] [ion] [status]?) - a net pair [short key: N]
|
||||
* pin([ion] [ion] [status]? [message]?) - a pin pair [short key: P]
|
||||
* device([ion] [ion] [status]? [message]?) - a device pair [short key: D]
|
||||
* circuit([ion] [ion] [status]? [message]?) - a subcircuit pair [short key: X]
|
||||
* net([ion] [ion] [status]? [message]?) - a net pair [short key: N]
|
||||
*
|
||||
* [non]
|
||||
*
|
||||
|
|
@ -110,6 +110,10 @@ namespace db
|
|||
*
|
||||
* <id> | ()
|
||||
*
|
||||
* [message]
|
||||
*
|
||||
* description(<name>) - error description [short key: B]
|
||||
*
|
||||
* [status]
|
||||
*
|
||||
* mismatch | - [short key: 0]
|
||||
|
|
|
|||
|
|
@ -112,6 +112,18 @@ void LayoutVsSchematicStandardReader::read_netlist (db::LayoutVsSchematic *lvs)
|
|||
}
|
||||
}
|
||||
|
||||
bool LayoutVsSchematicStandardReader::read_message (std::string &msg)
|
||||
{
|
||||
if (test (skeys::description_key) || test (lkeys::description_key)) {
|
||||
Brace br (this);
|
||||
read_word_or_quoted (msg);
|
||||
br.done ();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool LayoutVsSchematicStandardReader::read_status (db::NetlistCrossReference::Status &status)
|
||||
{
|
||||
if (test (skeys::match_key) || test (lkeys::match_key)) {
|
||||
|
|
@ -189,11 +201,14 @@ void LayoutVsSchematicStandardReader::read_xref (db::NetlistCrossReference *xref
|
|||
xref->gen_begin_circuit (circuit_a, circuit_b);
|
||||
|
||||
db::NetlistCrossReference::Status status = db::NetlistCrossReference::None;
|
||||
std::string msg;
|
||||
|
||||
while (br) {
|
||||
|
||||
if (read_status (status)) {
|
||||
// continue
|
||||
} else if (read_message (msg)) {
|
||||
// continue
|
||||
} else if (test (skeys::xref_key) || test (lkeys::xref_key)) {
|
||||
read_xrefs_for_circuits (xref, circuit_a, circuit_b);
|
||||
} else if (at_end ()) {
|
||||
|
|
@ -204,7 +219,7 @@ void LayoutVsSchematicStandardReader::read_xref (db::NetlistCrossReference *xref
|
|||
|
||||
}
|
||||
|
||||
xref->gen_end_circuit (circuit_a, circuit_b, status);
|
||||
xref->gen_end_circuit (circuit_a, circuit_b, status, msg);
|
||||
|
||||
br.done ();
|
||||
|
||||
|
|
@ -325,11 +340,13 @@ void LayoutVsSchematicStandardReader::read_net_pair (db::NetlistCrossReference *
|
|||
ion_b = read_ion ();
|
||||
|
||||
db::NetlistCrossReference::Status status = db::NetlistCrossReference::None;
|
||||
std::string msg;
|
||||
read_status (status);
|
||||
read_message (msg);
|
||||
|
||||
br.done ();
|
||||
|
||||
xref->gen_nets (net_by_numerical_id (circuit_a, ion_a, m_map_per_circuit_a), net_by_numerical_id (circuit_b, ion_b, m_map_per_circuit_b), status);
|
||||
xref->gen_nets (net_by_numerical_id (circuit_a, ion_a, m_map_per_circuit_a), net_by_numerical_id (circuit_b, ion_b, m_map_per_circuit_b), status, msg);
|
||||
}
|
||||
|
||||
void LayoutVsSchematicStandardReader::read_pin_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b)
|
||||
|
|
@ -341,11 +358,13 @@ void LayoutVsSchematicStandardReader::read_pin_pair (db::NetlistCrossReference *
|
|||
ion_b = read_ion ();
|
||||
|
||||
db::NetlistCrossReference::Status status = db::NetlistCrossReference::None;
|
||||
std::string msg;
|
||||
read_status (status);
|
||||
read_message (msg);
|
||||
|
||||
br.done ();
|
||||
|
||||
xref->gen_pins (pin_by_numerical_id (circuit_a, ion_a), pin_by_numerical_id (circuit_b, ion_b), status);
|
||||
xref->gen_pins (pin_by_numerical_id (circuit_a, ion_a), pin_by_numerical_id (circuit_b, ion_b), status, msg);
|
||||
}
|
||||
|
||||
void LayoutVsSchematicStandardReader::read_device_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b)
|
||||
|
|
@ -357,11 +376,13 @@ void LayoutVsSchematicStandardReader::read_device_pair (db::NetlistCrossReferenc
|
|||
ion_b = read_ion ();
|
||||
|
||||
db::NetlistCrossReference::Status status = db::NetlistCrossReference::None;
|
||||
std::string msg;
|
||||
read_status (status);
|
||||
read_message (msg);
|
||||
|
||||
br.done ();
|
||||
|
||||
xref->gen_devices (device_by_numerical_id (circuit_a, ion_a, m_map_per_circuit_a), device_by_numerical_id (circuit_b, ion_b, m_map_per_circuit_b), status);
|
||||
xref->gen_devices (device_by_numerical_id (circuit_a, ion_a, m_map_per_circuit_a), device_by_numerical_id (circuit_b, ion_b, m_map_per_circuit_b), status, msg);
|
||||
}
|
||||
|
||||
void LayoutVsSchematicStandardReader::read_subcircuit_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b)
|
||||
|
|
@ -373,11 +394,13 @@ void LayoutVsSchematicStandardReader::read_subcircuit_pair (db::NetlistCrossRefe
|
|||
ion_b = read_ion ();
|
||||
|
||||
db::NetlistCrossReference::Status status = db::NetlistCrossReference::None;
|
||||
std::string msg;
|
||||
read_status (status);
|
||||
read_message (msg);
|
||||
|
||||
br.done ();
|
||||
|
||||
xref->gen_subcircuits (subcircuit_by_numerical_id (circuit_a, ion_a, m_map_per_circuit_a), subcircuit_by_numerical_id (circuit_b, ion_b, m_map_per_circuit_b), status);
|
||||
xref->gen_subcircuits (subcircuit_by_numerical_id (circuit_a, ion_a, m_map_per_circuit_a), subcircuit_by_numerical_id (circuit_b, ion_b, m_map_per_circuit_b), status, msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ private:
|
|||
void read_netlist (db::LayoutVsSchematic *lvs);
|
||||
|
||||
bool read_status (db::NetlistCrossReference::Status &status);
|
||||
bool read_message (std::string &msg);
|
||||
void read_xref (db::NetlistCrossReference *xref);
|
||||
void read_xrefs_for_circuits (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b);
|
||||
void read_net_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ private:
|
|||
}
|
||||
|
||||
std::string status_to_s (const db::NetlistCrossReference::Status status);
|
||||
std::string message_to_s (const std::string &msg);
|
||||
void write (const db::NetlistCrossReference *xref);
|
||||
|
||||
std::map<const db::Circuit *, std::map<const db::Net *, unsigned int> > m_net2id_per_circuit_a, m_net2id_per_circuit_b;
|
||||
|
|
@ -145,7 +146,7 @@ std::string ion_to_s (const Obj *obj)
|
|||
}
|
||||
}
|
||||
|
||||
std::string net_id_to_s (const db::Net *net, const std::map<const db::Net *, unsigned int> &net2id)
|
||||
static std::string net_id_to_s (const db::Net *net, const std::map<const db::Net *, unsigned int> &net2id)
|
||||
{
|
||||
if (net) {
|
||||
std::map<const db::Net *, unsigned int>::const_iterator i = net2id.find (net);
|
||||
|
|
@ -156,6 +157,37 @@ std::string net_id_to_s (const db::Net *net, const std::map<const db::Net *, uns
|
|||
}
|
||||
}
|
||||
|
||||
static void build_pin_index_map (const db::Circuit *c, std::map<const db::Pin *, unsigned int> &pin2index)
|
||||
{
|
||||
if (c) {
|
||||
size_t pi = 0;
|
||||
for (db::Circuit::const_pin_iterator p = c->begin_pins (); p != c->end_pins (); ++p, ++pi) {
|
||||
pin2index.insert (std::make_pair (p.operator-> (), pi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string pin_id_to_s (const db::Pin *pin, const std::map<const db::Pin *, unsigned int> &pin2index)
|
||||
{
|
||||
if (pin) {
|
||||
std::map<const db::Pin *, unsigned int>::const_iterator i = pin2index.find (pin);
|
||||
tl_assert (i != pin2index.end ());
|
||||
return tl::to_string (i->second);
|
||||
} else {
|
||||
return "()";
|
||||
}
|
||||
}
|
||||
|
||||
template <class Keys>
|
||||
std::string std_writer_impl<Keys>::message_to_s (const std::string &msg)
|
||||
{
|
||||
if (msg.empty ()) {
|
||||
return std::string ();
|
||||
} else {
|
||||
return " " + Keys::description_key + "(" + tl::to_word_or_quoted_string (msg) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
template <class Keys>
|
||||
std::string std_writer_impl<Keys>::status_to_s (const db::NetlistCrossReference::Status status)
|
||||
{
|
||||
|
|
@ -182,23 +214,27 @@ void std_writer_impl<Keys>::write (const db::NetlistCrossReference *xref)
|
|||
const db::NetlistCrossReference::PerCircuitData *pcd = xref->per_circuit_data_for (*c);
|
||||
tl_assert (pcd != 0);
|
||||
|
||||
stream () << indent1 << Keys::circuit_key << "(" << name_to_s (c->first) << " " << name_to_s (c->second) << status_to_s (pcd->status) << endl;
|
||||
stream () << indent1 << Keys::circuit_key << "(" << name_to_s (c->first) << " " << name_to_s (c->second) << status_to_s (pcd->status) << message_to_s (pcd->msg) << endl;
|
||||
stream () << indent2 << Keys::xref_key << "(" << endl;
|
||||
|
||||
for (db::NetlistCrossReference::PerCircuitData::net_pairs_const_iterator n = pcd->nets.begin (); n != pcd->nets.end (); ++n) {
|
||||
stream () << indent1 << indent2 << Keys::net_key << "(" << net_id_to_s (n->pair.first, m_net2id_per_circuit_a [c->first]) << " " << net_id_to_s (n->pair.second, m_net2id_per_circuit_b [c->second]) << status_to_s (n->status) << ")" << endl;
|
||||
stream () << indent1 << indent2 << Keys::net_key << "(" << net_id_to_s (n->pair.first, m_net2id_per_circuit_a [c->first]) << " " << net_id_to_s (n->pair.second, m_net2id_per_circuit_b [c->second]) << status_to_s (n->status) << message_to_s (n->msg) << ")" << endl;
|
||||
}
|
||||
|
||||
std::map<const db::Pin *, unsigned int> pin2index_a, pin2index_b;
|
||||
build_pin_index_map (c->first, pin2index_a);
|
||||
build_pin_index_map (c->second, pin2index_b);
|
||||
|
||||
for (db::NetlistCrossReference::PerCircuitData::pin_pairs_const_iterator n = pcd->pins.begin (); n != pcd->pins.end (); ++n) {
|
||||
stream () << indent1 << indent2 << Keys::pin_key << "(" << ion_to_s (n->pair.first) << " " << ion_to_s (n->pair.second) << status_to_s (n->status) << ")" << endl;
|
||||
stream () << indent1 << indent2 << Keys::pin_key << "(" << pin_id_to_s (n->pair.first, pin2index_a) << " " << pin_id_to_s (n->pair.second, pin2index_b) << status_to_s (n->status) << message_to_s (n->msg) << ")" << endl;
|
||||
}
|
||||
|
||||
for (db::NetlistCrossReference::PerCircuitData::device_pairs_const_iterator n = pcd->devices.begin (); n != pcd->devices.end (); ++n) {
|
||||
stream () << indent1 << indent2 << Keys::device_key << "(" << ion_to_s (n->pair.first) << " " << ion_to_s (n->pair.second) << status_to_s (n->status) << ")" << endl;
|
||||
stream () << indent1 << indent2 << Keys::device_key << "(" << ion_to_s (n->pair.first) << " " << ion_to_s (n->pair.second) << status_to_s (n->status) << message_to_s (n->msg) << ")" << endl;
|
||||
}
|
||||
|
||||
for (db::NetlistCrossReference::PerCircuitData::subcircuit_pairs_const_iterator n = pcd->subcircuits.begin (); n != pcd->subcircuits.end (); ++n) {
|
||||
stream () << indent1 << indent2 << Keys::circuit_key << "(" << ion_to_s (n->pair.first) << " " << ion_to_s (n->pair.second) << status_to_s (n->status) << ")" << endl;
|
||||
stream () << indent1 << indent2 << Keys::circuit_key << "(" << ion_to_s (n->pair.first) << " " << ion_to_s (n->pair.second) << status_to_s (n->status) << message_to_s (n->msg) << ")" << endl;
|
||||
}
|
||||
|
||||
stream () << indent2 << ")" << endl;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ enum OnEmptyIntruderHint {
|
|||
*/
|
||||
Copy,
|
||||
|
||||
/**
|
||||
* @brief Copy the subject shape to the second result
|
||||
*/
|
||||
CopyToSecond,
|
||||
|
||||
/**
|
||||
* @brief Drop the subject shape
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ public:
|
|||
* @brief A generic categorizer
|
||||
*
|
||||
* The objective of this class is to supply a category ID for a given object.
|
||||
* The category ID also identities equivalent objects from netlist A and B.
|
||||
* The category ID also identifies equivalent objects from netlist A and B.
|
||||
*/
|
||||
template <class Obj>
|
||||
class generic_categorizer
|
||||
|
|
@ -2991,6 +2991,23 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
|||
}
|
||||
}
|
||||
|
||||
// impose the compare tolerances of the layout (first netlist) on the schematic (second netlist)
|
||||
// TODO: this is kind of clumsy. But it's very important to use the same device sorting for both netlists, so we play this trick.
|
||||
// A better solution was to have a common compare framework for both netlists.
|
||||
for (std::map<size_t, std::pair<const db::DeviceClass *, const db::DeviceClass *> >::const_iterator i = cat2dc.begin (); i != cat2dc.end (); ++i) {
|
||||
|
||||
if (i->second.first && i->second.second) {
|
||||
|
||||
const db::DeviceClass *da = i->second.first;
|
||||
db::DeviceClass *db = const_cast<db::DeviceClass *> (i->second.second);
|
||||
|
||||
const db::DeviceParameterCompareDelegate *cmp = da->parameter_compare_delegate ();
|
||||
db->set_parameter_compare_delegate (cmp ? cmp->clone () : 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// device whether to use a device category in strict mode
|
||||
|
||||
device_categorizer.clear_strict_device_categories ();
|
||||
|
|
@ -3083,7 +3100,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
|||
} else {
|
||||
|
||||
if (mp_logger) {
|
||||
mp_logger->circuit_skipped (ca, cb);
|
||||
mp_logger->circuit_skipped (ca, cb, generate_subcircuits_not_verified_warning (ca, verified_circuits_a, cb, verified_circuits_b));
|
||||
good = false;
|
||||
}
|
||||
|
||||
|
|
@ -3130,24 +3147,61 @@ NetlistComparer::derive_pin_equivalence (const db::Circuit *ca, const db::Circui
|
|||
circuit_pin_mapper->map_pins (cb, pb);
|
||||
}
|
||||
|
||||
static bool is_valid_circuit (const db::Circuit *c)
|
||||
{
|
||||
// typical via subcircuits attach through one pin. We can safely ignore such subcircuits because they don't
|
||||
// contribute graph edges.
|
||||
return c->pin_count () > 1;
|
||||
}
|
||||
|
||||
bool
|
||||
NetlistComparer::all_subcircuits_verified (const db::Circuit *c, const std::set<const db::Circuit *> &verified_circuits) const
|
||||
{
|
||||
for (db::Circuit::const_subcircuit_iterator sc = c->begin_subcircuits (); sc != c->end_subcircuits (); ++sc) {
|
||||
|
||||
const db::Circuit *cr = sc->circuit_ref ();
|
||||
|
||||
// typical via subcircuits attach through one pin. We can safely ignore such subcircuits because they don't
|
||||
// contribute graph edges.
|
||||
if (cr->pin_count () > 1 && verified_circuits.find (cr) == verified_circuits.end ()) {
|
||||
if (is_valid_circuit (cr) && verified_circuits.find (cr) == verified_circuits.end ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::vector<std::string> unverified_names (const db::Circuit *c, const std::set<const db::Circuit *> &verified_circuits)
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
std::set<const db::Circuit *> seen;
|
||||
for (db::Circuit::const_subcircuit_iterator sc = c->begin_subcircuits (); sc != c->end_subcircuits (); ++sc) {
|
||||
const db::Circuit *cr = sc->circuit_ref ();
|
||||
if (is_valid_circuit (cr) && seen.find (cr) == seen.end () && verified_circuits.find (cr) == verified_circuits.end ()) {
|
||||
seen.insert (cr);
|
||||
names.push_back (cr->name ());
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (names.begin (), names.end ());
|
||||
return names;
|
||||
}
|
||||
|
||||
std::string
|
||||
NetlistComparer::generate_subcircuits_not_verified_warning (const db::Circuit *ca, const std::set<const db::Circuit *> &verified_circuits_a, const db::Circuit *cb, const std::set<const db::Circuit *> &verified_circuits_b) const
|
||||
{
|
||||
std::string msg = tl::sprintf (tl::to_string (tr ("Circuits %s and %s could not be compared because the following subcircuits failed to compare:")), ca->name (), cb->name ());
|
||||
|
||||
std::vector<std::string> names_a = unverified_names (ca, verified_circuits_a);
|
||||
if (! names_a.empty ()) {
|
||||
msg += "\n A: " + tl::join (names_a, ",");
|
||||
}
|
||||
|
||||
std::vector<std::string> names_b = unverified_names (cb, verified_circuits_b);
|
||||
if (! names_b.empty ()) {
|
||||
msg += "\n B: " + tl::join (names_b, ",");
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<size_t, size_t> >
|
||||
compute_device_key (const db::Device &device, const db::NetGraph &g, bool strict)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public:
|
|||
* @brief There is a device class mismatch
|
||||
* "a" is null if there is no match for b and vice versa.
|
||||
*/
|
||||
virtual void device_class_mismatch (const db::DeviceClass * /*a*/, const db::DeviceClass * /*b*/) { }
|
||||
virtual void device_class_mismatch (const db::DeviceClass * /*a*/, const db::DeviceClass * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Begin logging for circuit a and b
|
||||
|
|
@ -74,19 +74,19 @@ public:
|
|||
/**
|
||||
* @brief End logging for circuit a and b
|
||||
*/
|
||||
virtual void end_circuit (const db::Circuit * /*a*/, const db::Circuit * /*b*/, bool /*matching*/) { }
|
||||
virtual void end_circuit (const db::Circuit * /*a*/, const db::Circuit * /*b*/, bool /*matching*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Circuits are skipped
|
||||
* Circuits are skipped if their subcircuits could not be matched.
|
||||
*/
|
||||
virtual void circuit_skipped (const db::Circuit * /*a*/, const db::Circuit * /*b*/) { }
|
||||
virtual void circuit_skipped (const db::Circuit * /*a*/, const db::Circuit * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief There is a circuit mismatch
|
||||
* "a" is null if there is no match for b and vice versa.
|
||||
*/
|
||||
virtual void circuit_mismatch (const db::Circuit * /*a*/, const db::Circuit * /*b*/) { }
|
||||
virtual void circuit_mismatch (const db::Circuit * /*a*/, const db::Circuit * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Nets a and b match exactly
|
||||
|
|
@ -98,7 +98,7 @@ public:
|
|||
* Other nets might also match with a and also with b. Matching this a and b is
|
||||
* an arbitrary decision.
|
||||
*/
|
||||
virtual void match_ambiguous_nets (const db::Net * /*a*/, const db::Net * /*b*/) { }
|
||||
virtual void match_ambiguous_nets (const db::Net * /*a*/, const db::Net * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Net a or b doesn't match
|
||||
|
|
@ -107,7 +107,7 @@ public:
|
|||
* nets are known not to match. Still the compare algorithm will proceed as
|
||||
* if these nets were equivalent to derive further matches.
|
||||
*/
|
||||
virtual void net_mismatch (const db::Net * /*a*/, const db::Net * /*b*/) { }
|
||||
virtual void net_mismatch (const db::Net * /*a*/, const db::Net * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Devices a and b match exactly
|
||||
|
|
@ -128,7 +128,7 @@ public:
|
|||
* @brief Device a or b doesn't match
|
||||
* "a" is null if there is no match for b and vice versa.
|
||||
*/
|
||||
virtual void device_mismatch (const db::Device * /*a*/, const db::Device * /*b*/) { }
|
||||
virtual void device_mismatch (const db::Device * /*a*/, const db::Device * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Pins a and b of the current circuit are matched
|
||||
|
|
@ -139,7 +139,7 @@ public:
|
|||
* @brief Pin a or b doesn't match
|
||||
* "a" is null if there is no match for b and vice versa.
|
||||
*/
|
||||
virtual void pin_mismatch (const db::Pin * /*a*/, const db::Pin * /*b*/) { }
|
||||
virtual void pin_mismatch (const db::Pin * /*a*/, const db::Pin * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
/**
|
||||
* @brief Subcircuits a and b match exactly
|
||||
|
|
@ -150,7 +150,7 @@ public:
|
|||
* @brief SubCircuit a or b doesn't match
|
||||
* "a" is null if there is no match for b and vice versa.
|
||||
*/
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit * /*a*/, const db::SubCircuit * /*b*/) { }
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit * /*a*/, const db::SubCircuit * /*b*/, const std::string & /*msg*/ = std::string ()) { }
|
||||
|
||||
private:
|
||||
// No copying
|
||||
|
|
@ -346,6 +346,7 @@ private:
|
|||
protected:
|
||||
bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector<std::pair<const Net *, const Net *> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const;
|
||||
bool all_subcircuits_verified (const db::Circuit *c, const std::set<const db::Circuit *> &verified_circuits) const;
|
||||
std::string generate_subcircuits_not_verified_warning (const db::Circuit *ca, const std::set<const db::Circuit *> &verified_circuits_a, const db::Circuit *cb, const std::set<const db::Circuit *> &verified_circuits_b) const;
|
||||
static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper);
|
||||
void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const;
|
||||
void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, db::DeviceEquivalenceTracker &device_eq, bool &good) const;
|
||||
|
|
|
|||
|
|
@ -338,9 +338,9 @@ NetlistCrossReference::establish_pair (const db::Circuit *a, const db::Circuit *
|
|||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::establish_pair (const db::Net *a, const db::Net *b, Status status)
|
||||
NetlistCrossReference::establish_pair (const db::Net *a, const db::Net *b, Status status, const std::string &msg)
|
||||
{
|
||||
mp_per_circuit_data->nets.push_back (NetPairData (a, b, status));
|
||||
mp_per_circuit_data->nets.push_back (NetPairData (a, b, status, msg));
|
||||
if (a) {
|
||||
m_other_net [a] = b;
|
||||
}
|
||||
|
|
@ -350,9 +350,9 @@ NetlistCrossReference::establish_pair (const db::Net *a, const db::Net *b, Statu
|
|||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::establish_pair (const db::Device *a, const db::Device *b, Status status)
|
||||
NetlistCrossReference::establish_pair (const db::Device *a, const db::Device *b, Status status, const std::string &msg)
|
||||
{
|
||||
mp_per_circuit_data->devices.push_back (DevicePairData (a, b, status));
|
||||
mp_per_circuit_data->devices.push_back (DevicePairData (a, b, status, msg));
|
||||
if (a) {
|
||||
m_other_device [a] = b;
|
||||
}
|
||||
|
|
@ -362,9 +362,9 @@ NetlistCrossReference::establish_pair (const db::Device *a, const db::Device *b,
|
|||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::establish_pair (const db::Pin *a, const db::Pin *b, Status status)
|
||||
NetlistCrossReference::establish_pair (const db::Pin *a, const db::Pin *b, Status status, const std::string &msg)
|
||||
{
|
||||
mp_per_circuit_data->pins.push_back (PinPairData (a, b, status));
|
||||
mp_per_circuit_data->pins.push_back (PinPairData (a, b, status, msg));
|
||||
if (a) {
|
||||
m_other_pin [a] = b;
|
||||
}
|
||||
|
|
@ -374,9 +374,9 @@ NetlistCrossReference::establish_pair (const db::Pin *a, const db::Pin *b, Statu
|
|||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::establish_pair (const db::SubCircuit *a, const db::SubCircuit *b, Status status)
|
||||
NetlistCrossReference::establish_pair (const db::SubCircuit *a, const db::SubCircuit *b, Status status, const std::string &msg)
|
||||
{
|
||||
mp_per_circuit_data->subcircuits.push_back (SubCircuitPairData (a, b, status));
|
||||
mp_per_circuit_data->subcircuits.push_back (SubCircuitPairData (a, b, status, msg));
|
||||
if (a) {
|
||||
m_other_subcircuit [a] = b;
|
||||
}
|
||||
|
|
@ -403,36 +403,37 @@ NetlistCrossReference::sort_circuit ()
|
|||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::gen_end_circuit (const db::Circuit *, const db::Circuit *, Status status)
|
||||
NetlistCrossReference::gen_end_circuit (const db::Circuit *, const db::Circuit *, Status status, const std::string &msg)
|
||||
{
|
||||
mp_per_circuit_data->status = status;
|
||||
mp_per_circuit_data->msg = msg;
|
||||
|
||||
m_current_circuits = std::make_pair((const db::Circuit *)0, (const db::Circuit *)0);
|
||||
mp_per_circuit_data = 0;
|
||||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::gen_nets (const db::Net *a, const db::Net *b, Status status)
|
||||
NetlistCrossReference::gen_nets (const db::Net *a, const db::Net *b, Status status, const std::string &msg)
|
||||
{
|
||||
establish_pair (a, b, status);
|
||||
establish_pair (a, b, status, msg);
|
||||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::gen_devices (const db::Device *a, const db::Device *b, Status status)
|
||||
NetlistCrossReference::gen_devices (const db::Device *a, const db::Device *b, Status status, const std::string &msg)
|
||||
{
|
||||
establish_pair (a, b, status);
|
||||
establish_pair (a, b, status, msg);
|
||||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::gen_pins (const db::Pin *a, const db::Pin *b, Status status)
|
||||
NetlistCrossReference::gen_pins (const db::Pin *a, const db::Pin *b, Status status, const std::string &msg)
|
||||
{
|
||||
establish_pair (a, b, status);
|
||||
establish_pair (a, b, status, msg);
|
||||
}
|
||||
|
||||
void
|
||||
NetlistCrossReference::gen_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b, Status status)
|
||||
NetlistCrossReference::gen_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b, Status status, const std::string &msg)
|
||||
{
|
||||
establish_pair (a, b, status);
|
||||
establish_pair (a, b, status, msg);
|
||||
}
|
||||
|
||||
static void init_data_from_single (const db::Net *net, NetlistCrossReference::PerNetData &data, bool first)
|
||||
|
|
|
|||
|
|
@ -61,44 +61,48 @@ public:
|
|||
{
|
||||
typedef db::Net object_type;
|
||||
|
||||
NetPairData (const db::Net *a, const db::Net *b, Status s) : pair (a, b), status (s) { }
|
||||
NetPairData (const db::Net *a, const db::Net *b, Status s, const std::string &m) : pair (a, b), status (s), msg (m) { }
|
||||
NetPairData () : pair ((const db::Net *)0, (const db::Net *)0), status (None) { }
|
||||
|
||||
std::pair<const db::Net *, const db::Net *> pair;
|
||||
Status status;
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
struct DevicePairData
|
||||
{
|
||||
typedef db::Device object_type;
|
||||
|
||||
DevicePairData (const db::Device *a, const db::Device *b, Status s) : pair (a, b), status (s) { }
|
||||
DevicePairData (const db::Device *a, const db::Device *b, Status s, const std::string &m) : pair (a, b), status (s), msg (m) { }
|
||||
DevicePairData () : pair ((const db::Device *)0, (const db::Device *)0), status (None) { }
|
||||
|
||||
std::pair<const db::Device *, const db::Device *> pair;
|
||||
Status status;
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
struct PinPairData
|
||||
{
|
||||
typedef db::Pin object_type;
|
||||
|
||||
PinPairData (const db::Pin *a, const db::Pin *b, Status s) : pair (a, b), status (s) { }
|
||||
PinPairData (const db::Pin *a, const db::Pin *b, Status s, const std::string &m) : pair (a, b), status (s), msg (m) { }
|
||||
PinPairData () : pair ((const db::Pin *)0, (const db::Pin *)0), status (None) { }
|
||||
|
||||
std::pair<const db::Pin *, const db::Pin *> pair;
|
||||
Status status;
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
struct SubCircuitPairData
|
||||
{
|
||||
typedef db::SubCircuit object_type;
|
||||
|
||||
SubCircuitPairData (const db::SubCircuit *a, const db::SubCircuit *b, Status s) : pair (a, b), status (s) { }
|
||||
SubCircuitPairData (const db::SubCircuit *a, const db::SubCircuit *b, Status s, const std::string &m) : pair (a, b), status (s), msg (m) { }
|
||||
SubCircuitPairData () : pair ((const db::SubCircuit *)0, (const db::SubCircuit *)0), status (None) { }
|
||||
|
||||
std::pair<const db::SubCircuit *, const db::SubCircuit *> pair;
|
||||
Status status;
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
struct PerCircuitData
|
||||
|
|
@ -115,6 +119,7 @@ public:
|
|||
typedef subcircuit_pairs_type::const_iterator subcircuit_pairs_const_iterator;
|
||||
|
||||
Status status;
|
||||
std::string msg;
|
||||
net_pairs_type nets;
|
||||
device_pairs_type devices;
|
||||
pin_pairs_type pins;
|
||||
|
|
@ -139,11 +144,11 @@ public:
|
|||
void gen_begin_netlist (const db::Netlist *a, const db::Netlist *b);
|
||||
void gen_end_netlist (const db::Netlist *a, const db::Netlist *b);
|
||||
void gen_begin_circuit (const db::Circuit *a, const db::Circuit *b);
|
||||
void gen_end_circuit (const db::Circuit *a, const db::Circuit *b, Status status);
|
||||
void gen_nets (const db::Net *a, const db::Net *b, Status status);
|
||||
void gen_devices (const db::Device *a, const db::Device *b, Status status);
|
||||
void gen_pins (const db::Pin *a, const db::Pin *b, Status status);
|
||||
void gen_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b, Status status);
|
||||
void gen_end_circuit (const db::Circuit *a, const db::Circuit *b, Status status, const std::string &msg);
|
||||
void gen_nets (const db::Net *a, const db::Net *b, Status status, const std::string &msg);
|
||||
void gen_devices (const db::Device *a, const db::Device *b, Status status, const std::string &msg);
|
||||
void gen_pins (const db::Pin *a, const db::Pin *b, Status status, const std::string &msg);
|
||||
void gen_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b, Status status, const std::string &msg);
|
||||
|
||||
// db::NetlistCompareLogger interface
|
||||
virtual void begin_netlist (const db::Netlist *a, const db::Netlist *b)
|
||||
|
|
@ -162,77 +167,77 @@ public:
|
|||
gen_begin_circuit (a, b);
|
||||
}
|
||||
|
||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching)
|
||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching, const std::string &msg)
|
||||
{
|
||||
sort_circuit ();
|
||||
gen_end_circuit (a, b, matching ? Match : NoMatch);
|
||||
gen_end_circuit (a, b, matching ? Match : NoMatch, msg);
|
||||
}
|
||||
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b, const std::string &msg)
|
||||
{
|
||||
gen_begin_circuit (a, b);
|
||||
gen_end_circuit (a, b, Skipped);
|
||||
gen_end_circuit (a, b, Skipped, msg);
|
||||
}
|
||||
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b, const std::string &msg)
|
||||
{
|
||||
gen_begin_circuit (a, b);
|
||||
gen_end_circuit (a, b, Mismatch);
|
||||
gen_end_circuit (a, b, Mismatch, msg);
|
||||
}
|
||||
|
||||
virtual void match_nets (const db::Net *a, const db::Net *b)
|
||||
{
|
||||
gen_nets (a, b, Match);
|
||||
gen_nets (a, b, Match, std::string ());
|
||||
}
|
||||
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b)
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b, const std::string &msg)
|
||||
{
|
||||
gen_nets (a, b, MatchWithWarning);
|
||||
gen_nets (a, b, MatchWithWarning, msg);
|
||||
}
|
||||
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b)
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b, const std::string &msg)
|
||||
{
|
||||
gen_nets (a, b, Mismatch);
|
||||
gen_nets (a, b, Mismatch, msg);
|
||||
}
|
||||
|
||||
virtual void match_devices (const db::Device *a, const db::Device *b)
|
||||
{
|
||||
gen_devices (a, b, Match);
|
||||
gen_devices (a, b, Match, std::string ());
|
||||
}
|
||||
|
||||
virtual void match_devices_with_different_parameters (const db::Device *a, const db::Device *b)
|
||||
{
|
||||
gen_devices (a, b, MatchWithWarning);
|
||||
gen_devices (a, b, MatchWithWarning, std::string ());
|
||||
}
|
||||
|
||||
virtual void match_devices_with_different_device_classes (const db::Device *a, const db::Device *b)
|
||||
{
|
||||
gen_devices (a, b, MatchWithWarning);
|
||||
gen_devices (a, b, MatchWithWarning, std::string ());
|
||||
}
|
||||
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b)
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b, const std::string &msg)
|
||||
{
|
||||
gen_devices (a, b, Mismatch);
|
||||
gen_devices (a, b, Mismatch, msg);
|
||||
}
|
||||
|
||||
virtual void match_pins (const db::Pin *a, const db::Pin *b)
|
||||
{
|
||||
gen_pins (a, b, Match);
|
||||
gen_pins (a, b, Match, std::string ());
|
||||
}
|
||||
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b)
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b, const std::string &msg)
|
||||
{
|
||||
gen_pins (a, b, Mismatch);
|
||||
gen_pins (a, b, Mismatch, msg);
|
||||
}
|
||||
|
||||
virtual void match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
{
|
||||
gen_subcircuits (a, b, Match);
|
||||
gen_subcircuits (a, b, Match, std::string ());
|
||||
}
|
||||
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b, const std::string &msg)
|
||||
{
|
||||
gen_subcircuits (a, b, Mismatch);
|
||||
gen_subcircuits (a, b, Mismatch, msg);
|
||||
}
|
||||
|
||||
void clear ();
|
||||
|
|
@ -292,10 +297,10 @@ private:
|
|||
PerCircuitData *mp_per_circuit_data;
|
||||
|
||||
void establish_pair (const db::Circuit *a, const db::Circuit *b);
|
||||
void establish_pair (const db::Net *a, const db::Net *b, Status status);
|
||||
void establish_pair (const db::Device *a, const db::Device *b, Status status);
|
||||
void establish_pair (const db::Pin *a, const db::Pin *b, Status status);
|
||||
void establish_pair (const db::SubCircuit *a, const db::SubCircuit *b, Status status);
|
||||
void establish_pair (const db::Net *a, const db::Net *b, Status status, const std::string &msg);
|
||||
void establish_pair (const db::Device *a, const db::Device *b, Status status, const std::string &msg);
|
||||
void establish_pair (const db::Pin *a, const db::Pin *b, Status status, const std::string &msg);
|
||||
void establish_pair (const db::SubCircuit *a, const db::SubCircuit *b, Status status, const std::string &msg);
|
||||
void sort_circuit ();
|
||||
void sort_netlist ();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_ind (new db::device_
|
|||
static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_diode (new db::device_class_template<db::DeviceClassDiode> ("DIODE"));
|
||||
static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_mos3 (new db::device_class_template<db::DeviceClassMOS3Transistor> ("MOS3"));
|
||||
static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_mos4 (new db::device_class_template<db::DeviceClassMOS4Transistor> ("MOS4"));
|
||||
static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_bjt3 (new db::device_class_template<db::DeviceClassBJT3Transistor> ("BJT3"));
|
||||
static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_bjt4 (new db::device_class_template<db::DeviceClassBJT4Transistor> ("BJT4"));
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassTwoTerminalDevice implementation
|
||||
|
|
|
|||
|
|
@ -267,6 +267,16 @@ public:
|
|||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Takes the underlying delegate object
|
||||
*/
|
||||
RegionDelegate *take_delegate ()
|
||||
{
|
||||
RegionDelegate *delegate = mp_delegate;
|
||||
mp_delegate = 0;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the base verbosity
|
||||
*
|
||||
|
|
@ -1132,6 +1142,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_outside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are completly outside polygons from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_outside and selected_not_outside, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_outside_differential (const Region &other) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_outside_pair (other);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which are completly inside polygons from the other region
|
||||
*
|
||||
|
|
@ -1178,6 +1201,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_inside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are completly inside polygons from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_inside and selected_not_inside, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_inside_differential (const Region &other) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_inside_pair (other);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are enclosing polygons from the other region
|
||||
*
|
||||
|
|
@ -1224,6 +1260,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_enclosing (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are completly enclosing polygons from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_enclosing and selected_not_enclosing, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_enclosing_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_enclosing_pair (other, min_count, max_count);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which overlap or touch polygons from the other region
|
||||
*
|
||||
|
|
@ -1278,6 +1327,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are interacting with polygons from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_interacting and selected_not_interacting, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_interacting_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which overlap or touch edges from the given edge collection
|
||||
*
|
||||
|
|
@ -1324,6 +1386,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are interacting with edges from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_interacting and selected_not_interacting, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_interacting_differential (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which overlap or touch texts from the text collection
|
||||
*
|
||||
|
|
@ -1370,6 +1445,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are interacting with texts from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_interacting and selected_not_interacting, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_interacting_differential (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which overlap polygons from the other region
|
||||
*
|
||||
|
|
@ -1416,6 +1504,19 @@ public:
|
|||
return Region (mp_delegate->selected_not_overlapping (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of this which are overlapping polygons from the other region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_overlapping and selected_not_overlapping, but faster.
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
std::pair<Region, Region> selected_overlapping_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_overlapping_pair (other, min_count, max_count);
|
||||
return std::pair<Region, Region> (Region (p.first), Region (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are inside polygons of this region
|
||||
*
|
||||
|
|
|
|||
|
|
@ -281,18 +281,25 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_inside (const Region &other) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -537,8 +537,8 @@ private:
|
|||
}
|
||||
|
||||
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, 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_other_is_merged (other_is_merged)
|
||||
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_mode (mode), m_touching (touching), m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -552,8 +552,13 @@ db::Coord interacting_local_operation<TS, TI, TR>::dist () const
|
|||
template <class TS, class TI, class TR>
|
||||
void interacting_local_operation<TS, TI, TR>::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
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
if (m_output_mode == None) {
|
||||
return;
|
||||
} else if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
tl_assert (results.size () == 1);
|
||||
} else {
|
||||
tl_assert (results.size () == 2);
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
|
|
@ -652,9 +657,21 @@ void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*l
|
|||
if (c != interaction_counts.end ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= m_min_count && count <= m_max_count) != m_inverse) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
result.insert (subject);
|
||||
bool good = (count >= m_min_count && count <= m_max_count);
|
||||
if (good) {
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
results [0].insert (subject);
|
||||
}
|
||||
} else {
|
||||
if (m_output_mode == Negative) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
// Yes, it's "positive_result" as this is the first one.
|
||||
results [0].insert (subject);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
results [1].insert (subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -663,11 +680,22 @@ template <class TS, class TI, class TR>
|
|||
OnEmptyIntruderHint
|
||||
interacting_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if ((m_mode <= 0) != m_inverse) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
if ((m_mode <= 0)) {
|
||||
if (m_output_mode == Positive) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::CopyToSecond;
|
||||
}
|
||||
} else {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
}
|
||||
}
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
|
|
@ -761,8 +789,8 @@ template class DB_PUBLIC pull_local_operation<db::Polygon, db::Polygon, db::Poly
|
|||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
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, bool other_is_merged)
|
||||
: 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)
|
||||
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -777,6 +805,14 @@ db::Coord interacting_with_edge_local_operation<TS, TI, TR>::dist () const
|
|||
template <class TS, class TI, class TR>
|
||||
void interacting_with_edge_local_operation<TS, TI, TR>::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
|
||||
{
|
||||
if (m_output_mode == None) {
|
||||
return;
|
||||
} else if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
tl_assert (results.size () == 1);
|
||||
} else {
|
||||
tl_assert (results.size () == 2);
|
||||
}
|
||||
|
||||
std::unordered_map<TR, size_t> counted_results;
|
||||
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
|
|
@ -829,7 +865,7 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
const TR *addressable = push_polygon_to_heap (layout, subject, heap);
|
||||
|
||||
scanner.insert1 (addressable, 0);
|
||||
if (m_inverse) {
|
||||
if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
|
||||
inserter.init (*addressable);
|
||||
}
|
||||
|
||||
|
|
@ -839,13 +875,18 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
|
||||
// select hits based on their count
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
|
||||
for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
if (hit) {
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
results [0].insert (r->first);
|
||||
}
|
||||
} else {
|
||||
if (m_output_mode == Negative) {
|
||||
results [0].insert (r->first);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
results [1].insert (r->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -853,10 +894,14 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
template <class TS, class TI, class TR>
|
||||
OnEmptyIntruderHint interacting_with_edge_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if (!m_inverse) {
|
||||
if (m_output_mode == Positive) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
} else {
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::CopyToSecond;
|
||||
} else {
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1000,8 +1045,8 @@ template class DB_PUBLIC pull_with_text_local_operation<db::Polygon, db::Text, d
|
|||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count)
|
||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count)
|
||||
: m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1017,6 +1062,14 @@ db::Coord interacting_with_text_local_operation<TS, TI, TR>::dist () const
|
|||
template <class TS, class TI, class TR>
|
||||
void interacting_with_text_local_operation<TS, TI, TR>::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
|
||||
{
|
||||
if (m_output_mode == None) {
|
||||
return;
|
||||
} else if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
tl_assert (results.size () == 1);
|
||||
} else {
|
||||
tl_assert (results.size () == 2);
|
||||
}
|
||||
|
||||
std::unordered_map<TR, size_t> counted_results;
|
||||
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
|
|
@ -1042,7 +1095,7 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
const TR *addressable = push_polygon_to_heap (layout, interactions.subject_shape (i->first), heap);
|
||||
|
||||
scanner.insert1 (addressable, 0);
|
||||
if (m_inverse) {
|
||||
if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
|
||||
inserter.init (*addressable);
|
||||
}
|
||||
|
||||
|
|
@ -1052,13 +1105,19 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
|
||||
// select hits based on their count
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
|
||||
for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
if (hit) {
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
results [0].insert (r->first);
|
||||
}
|
||||
} else {
|
||||
if (m_output_mode == Negative) {
|
||||
// Yes. It's "positive"! This is the first output.
|
||||
results [0].insert (r->first);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
results [1].insert (r->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1066,10 +1125,14 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
template <class TS, class TI, class TR>
|
||||
OnEmptyIntruderHint interacting_with_text_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if (!m_inverse) {
|
||||
if (m_output_mode == Positive) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
} else {
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::CopyToSecond;
|
||||
} else {
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -222,12 +222,16 @@ private:
|
|||
|
||||
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
|
||||
|
||||
enum InteractingOutputMode {
|
||||
None = 0, Positive = 1, Negative = 2, PositiveAndNegative = 3
|
||||
};
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class interacting_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
|
||||
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;
|
||||
|
|
@ -237,7 +241,7 @@ public:
|
|||
private:
|
||||
int m_mode;
|
||||
bool m_touching;
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
|
@ -268,7 +272,7 @@ class interacting_with_edge_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
|
||||
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;
|
||||
|
|
@ -276,7 +280,7 @@ public:
|
|||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
|
@ -303,7 +307,7 @@ class interacting_with_text_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count);
|
||||
interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count);
|
||||
|
||||
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;
|
||||
|
|
@ -311,7 +315,7 @@ public:
|
|||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -190,17 +190,17 @@ public:
|
|||
m_circuit = circuit2str (a) + " vs. " + circuit2str (b);
|
||||
}
|
||||
|
||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b)
|
||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("device_class_mismatch " + device_class2str (a) + " " + device_class2str (b));
|
||||
}
|
||||
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("circuit_skipped " + circuit2str (a) + " " + circuit2str (b));
|
||||
}
|
||||
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("circuit_mismatch " + circuit2str (a) + " " + circuit2str (b));
|
||||
}
|
||||
|
|
@ -210,12 +210,12 @@ public:
|
|||
out ("match_nets " + net2str (a) + " " + net2str (b));
|
||||
}
|
||||
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b)
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("match_ambiguous_nets " + net2str (a) + " " + net2str (b));
|
||||
}
|
||||
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b)
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("net_mismatch " + net2str (a) + " " + net2str (b));
|
||||
}
|
||||
|
|
@ -225,7 +225,7 @@ public:
|
|||
out ("match_devices " + device2str (a) + " " + device2str (b));
|
||||
}
|
||||
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b)
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("device_mismatch " + device2str (a) + " " + device2str (b));
|
||||
}
|
||||
|
|
@ -245,7 +245,7 @@ public:
|
|||
out ("match_pins " + pin2str (a) + " " + pin2str (b));
|
||||
}
|
||||
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b)
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("pin_mismatch " + pin2str (a) + " " + pin2str (b));
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ public:
|
|||
out ("match_subcircuits " + subcircuit2str (a) + " " + subcircuit2str (b));
|
||||
}
|
||||
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("subcircuit_mismatch " + subcircuit2str (a) + " " + subcircuit2str (b));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,18 +66,18 @@ public:
|
|||
db::NetlistCompareLogger::end_netlist (a, b);
|
||||
}
|
||||
|
||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b)
|
||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b, const std::string &msg)
|
||||
{
|
||||
if (cb_device_class_mismatch.can_issue ()) {
|
||||
cb_device_class_mismatch.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::device_class_mismatch_fb, a, b);
|
||||
cb_device_class_mismatch.issue<GenericNetlistCompareLogger, const db::DeviceClass *, const db::DeviceClass *, const std::string &> (&GenericNetlistCompareLogger::device_class_mismatch_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::device_class_mismatch (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void device_class_mismatch_fb (const db::DeviceClass *a, const db::DeviceClass *b)
|
||||
void device_class_mismatch_fb (const db::DeviceClass *a, const db::DeviceClass *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::device_class_mismatch (a, b);
|
||||
db::NetlistCompareLogger::device_class_mismatch (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void begin_circuit (const db::Circuit *a, const db::Circuit *b)
|
||||
|
|
@ -94,46 +94,46 @@ public:
|
|||
db::NetlistCompareLogger::begin_circuit (a, b);
|
||||
}
|
||||
|
||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching)
|
||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching, const std::string &msg)
|
||||
{
|
||||
if (cb_end_circuit.can_issue ()) {
|
||||
cb_end_circuit.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::end_circuit_fb, a, b, matching);
|
||||
cb_end_circuit.issue<GenericNetlistCompareLogger, const db::Circuit *, const db::Circuit *, bool, const std::string &> (&GenericNetlistCompareLogger::end_circuit_fb, a, b, matching, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::end_circuit (a, b, matching);
|
||||
}
|
||||
}
|
||||
|
||||
void end_circuit_fb (const db::Circuit *a, const db::Circuit *b, bool matching)
|
||||
void end_circuit_fb (const db::Circuit *a, const db::Circuit *b, bool matching, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::end_circuit (a, b, matching);
|
||||
db::NetlistCompareLogger::end_circuit (a, b, matching, msg);
|
||||
}
|
||||
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b, const std::string &msg)
|
||||
{
|
||||
if (cb_circuit_skipped.can_issue ()) {
|
||||
cb_circuit_skipped.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::circuit_skipped_fb, a, b);
|
||||
cb_circuit_skipped.issue<GenericNetlistCompareLogger, const db::Circuit *, const db::Circuit *, const std::string &> (&GenericNetlistCompareLogger::circuit_skipped_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::circuit_skipped (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void circuit_skipped_fb (const db::Circuit *a, const db::Circuit *b)
|
||||
void circuit_skipped_fb (const db::Circuit *a, const db::Circuit *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::circuit_skipped (a, b);
|
||||
db::NetlistCompareLogger::circuit_skipped (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b, const std::string &msg)
|
||||
{
|
||||
if (cb_circuit_mismatch.can_issue ()) {
|
||||
cb_circuit_mismatch.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::circuit_mismatch_fb, a, b);
|
||||
cb_circuit_mismatch.issue<GenericNetlistCompareLogger, const db::Circuit *, const db::Circuit *, const std::string &> (&GenericNetlistCompareLogger::circuit_mismatch_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::circuit_mismatch (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void circuit_mismatch_fb (const db::Circuit *a, const db::Circuit *b)
|
||||
void circuit_mismatch_fb (const db::Circuit *a, const db::Circuit *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::circuit_mismatch (a, b);
|
||||
db::NetlistCompareLogger::circuit_mismatch (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void match_nets (const db::Net *a, const db::Net *b)
|
||||
|
|
@ -150,32 +150,32 @@ public:
|
|||
db::NetlistCompareLogger::match_nets (a, b);
|
||||
}
|
||||
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b)
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b, const std::string &msg)
|
||||
{
|
||||
if (cb_match_ambiguous_nets.can_issue ()) {
|
||||
cb_match_ambiguous_nets.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::match_ambiguous_nets_fb, a, b);
|
||||
cb_match_ambiguous_nets.issue<GenericNetlistCompareLogger, const db::Net *, const db::Net *, const std::string &> (&GenericNetlistCompareLogger::match_ambiguous_nets_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::match_ambiguous_nets (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void match_ambiguous_nets_fb (const db::Net *a, const db::Net *b)
|
||||
void match_ambiguous_nets_fb (const db::Net *a, const db::Net *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::match_ambiguous_nets (a, b);
|
||||
db::NetlistCompareLogger::match_ambiguous_nets (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b)
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b, const std::string &msg)
|
||||
{
|
||||
if (cb_net_mismatch.can_issue ()) {
|
||||
cb_net_mismatch.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::net_mismatch_fb, a, b);
|
||||
cb_net_mismatch.issue<GenericNetlistCompareLogger, const db::Net *, const db::Net *, const std::string &> (&GenericNetlistCompareLogger::net_mismatch_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::net_mismatch (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void net_mismatch_fb (const db::Net *a, const db::Net *b)
|
||||
void net_mismatch_fb (const db::Net *a, const db::Net *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::net_mismatch (a, b);
|
||||
db::NetlistCompareLogger::net_mismatch (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void match_devices (const db::Device *a, const db::Device *b)
|
||||
|
|
@ -220,18 +220,18 @@ public:
|
|||
db::NetlistCompareLogger::match_devices_with_different_device_classes (a, b);
|
||||
}
|
||||
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b)
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b, const std::string &msg)
|
||||
{
|
||||
if (cb_device_mismatch.can_issue ()) {
|
||||
cb_device_mismatch.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::device_mismatch_fb, a, b);
|
||||
cb_device_mismatch.issue<GenericNetlistCompareLogger, const db::Device *, const db::Device *, const std::string &> (&GenericNetlistCompareLogger::device_mismatch_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::device_mismatch (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void device_mismatch_fb (const db::Device *a, const db::Device *b)
|
||||
void device_mismatch_fb (const db::Device *a, const db::Device *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::device_mismatch (a, b);
|
||||
db::NetlistCompareLogger::device_mismatch (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void match_pins (const db::Pin *a, const db::Pin *b)
|
||||
|
|
@ -248,18 +248,18 @@ public:
|
|||
db::NetlistCompareLogger::match_pins (a, b);
|
||||
}
|
||||
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b)
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b, const std::string &msg)
|
||||
{
|
||||
if (cb_pin_mismatch.can_issue ()) {
|
||||
cb_pin_mismatch.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::pin_mismatch_fb, a, b);
|
||||
cb_pin_mismatch.issue<GenericNetlistCompareLogger, const db::Pin *, const db::Pin *, const std::string &> (&GenericNetlistCompareLogger::pin_mismatch_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::pin_mismatch (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void pin_mismatch_fb (const db::Pin *a, const db::Pin *b)
|
||||
void pin_mismatch_fb (const db::Pin *a, const db::Pin *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::pin_mismatch (a, b);
|
||||
db::NetlistCompareLogger::pin_mismatch (a, b, msg);
|
||||
}
|
||||
|
||||
virtual void match_subcircuits (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
|
|
@ -276,18 +276,18 @@ public:
|
|||
db::NetlistCompareLogger::match_subcircuits (a, b);
|
||||
}
|
||||
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b, const std::string &msg)
|
||||
{
|
||||
if (cb_subcircuit_mismatch.can_issue ()) {
|
||||
cb_subcircuit_mismatch.issue<GenericNetlistCompareLogger> (&GenericNetlistCompareLogger::subcircuit_mismatch_fb, a, b);
|
||||
cb_subcircuit_mismatch.issue<GenericNetlistCompareLogger, const db::SubCircuit *, const db::SubCircuit *, const std::string &> (&GenericNetlistCompareLogger::subcircuit_mismatch_fb, a, b, msg);
|
||||
} else {
|
||||
db::NetlistCompareLogger::subcircuit_mismatch (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void subcircuit_mismatch_fb (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
void subcircuit_mismatch_fb (const db::SubCircuit *a, const db::SubCircuit *b, const std::string &msg)
|
||||
{
|
||||
db::NetlistCompareLogger::subcircuit_mismatch (a, b);
|
||||
db::NetlistCompareLogger::subcircuit_mismatch (a, b, msg);
|
||||
}
|
||||
|
||||
gsi::Callback cb_begin_netlist;
|
||||
|
|
@ -339,7 +339,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
|
|||
"@brief This function is called at the end of the compare process.\n"
|
||||
"This method is called once when the compare run ended.\n"
|
||||
) +
|
||||
gsi::callback ("device_class_mismatch", &GenericNetlistCompareLogger::device_class_mismatch, &GenericNetlistCompareLogger::cb_device_class_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("device_class_mismatch", &GenericNetlistCompareLogger::device_class_mismatch, &GenericNetlistCompareLogger::cb_device_class_mismatch, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when device classes can't be compared.\n"
|
||||
"This method is called when a device class can't be mapped to a partner in the other netlist. In this case, "
|
||||
"this method is called with the one device class and nil for the other class.\n"
|
||||
|
|
@ -354,19 +354,19 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
|
|||
"some or all subcircuits the pin assignment can't be derived. In this case, \\circuit_skipped will be called once "
|
||||
"instead of \\begin_circuit and \\end_circuit.\n"
|
||||
) +
|
||||
gsi::callback ("end_circuit", &GenericNetlistCompareLogger::end_circuit, &GenericNetlistCompareLogger::cb_end_circuit, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("matching"),
|
||||
gsi::callback ("end_circuit", &GenericNetlistCompareLogger::end_circuit, &GenericNetlistCompareLogger::cb_end_circuit, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("matching"), gsi::arg ("msg"),
|
||||
"@brief This function is called at the end of the compare process.\n"
|
||||
"The 'matching' argument indicates whether the circuits have been identified as identical.\n"
|
||||
"See \\begin_circuit for details."
|
||||
) +
|
||||
gsi::callback ("circuit_skipped", &GenericNetlistCompareLogger::circuit_skipped, &GenericNetlistCompareLogger::cb_circuit_skipped, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("circuit_skipped", &GenericNetlistCompareLogger::circuit_skipped, &GenericNetlistCompareLogger::cb_circuit_skipped, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when circuits can't be compared.\n"
|
||||
"If there is a known circuit pair, but the circuits can be compared - for example because subcircuits can't be identified - this method will be called with "
|
||||
"both circuits.\n"
|
||||
"\n"
|
||||
"This method is called instead of \\begin_circuit and \\end_circuit."
|
||||
) +
|
||||
gsi::callback ("circuit_mismatch", &GenericNetlistCompareLogger::circuit_mismatch, &GenericNetlistCompareLogger::cb_circuit_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("circuit_mismatch", &GenericNetlistCompareLogger::circuit_mismatch, &GenericNetlistCompareLogger::cb_circuit_mismatch, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when circuits can't be compared.\n"
|
||||
"This method is called when a circuit can't be mapped to a partner in the other netlist. In this case, "
|
||||
"this method is called with the one circuit and nil for the other circuit.\n"
|
||||
|
|
@ -379,13 +379,13 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
|
|||
"If the nets can be paired, but this match is ambiguous, \\match_ambiguous_nets will be called instead.\n"
|
||||
"If nets can't be matched to a partner, \\net_mismatch will be called.\n"
|
||||
) +
|
||||
gsi::callback ("match_ambiguous_nets", &GenericNetlistCompareLogger::match_ambiguous_nets, &GenericNetlistCompareLogger::cb_match_ambiguous_nets, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("match_ambiguous_nets", &GenericNetlistCompareLogger::match_ambiguous_nets, &GenericNetlistCompareLogger::cb_match_ambiguous_nets, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when two nets are identified, but this choice is ambiguous.\n"
|
||||
"This choice is a last-resort fallback to allow continuation of the compare procedure. It is likely that this "
|
||||
"compare will fail later. Looking for ambiguous nets allows deduction of the origin of this faulty decision. "
|
||||
"See \\match_nets for more details."
|
||||
) +
|
||||
gsi::callback ("net_mismatch", &GenericNetlistCompareLogger::net_mismatch, &GenericNetlistCompareLogger::cb_net_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("net_mismatch", &GenericNetlistCompareLogger::net_mismatch, &GenericNetlistCompareLogger::cb_net_mismatch, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when a net can't be paired.\n"
|
||||
"This method will be called, if a net cannot be identified as identical with another net. The corresponding argument "
|
||||
"will identify the net and source netlist. The other argument will be nil.\n"
|
||||
|
|
@ -409,7 +409,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
|
|||
"@brief This function is called when two devices are identified but have different device classes.\n"
|
||||
"See \\match_devices for details.\n"
|
||||
) +
|
||||
gsi::callback ("device_mismatch", &GenericNetlistCompareLogger::device_mismatch, &GenericNetlistCompareLogger::cb_device_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("device_mismatch", &GenericNetlistCompareLogger::device_mismatch, &GenericNetlistCompareLogger::cb_device_mismatch, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when two devices can't be paired.\n"
|
||||
"This will report the device considered in a or b. The other argument is nil. "
|
||||
"See \\match_devices for details.\n"
|
||||
|
|
@ -419,7 +419,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
|
|||
"If two pins are identified as a corresponding pair, this method will be called with both pins.\n"
|
||||
"If pins can't be matched, \\pin_mismatch will be called with the one pin considered and the other pin being nil."
|
||||
) +
|
||||
gsi::callback ("pin_mismatch", &GenericNetlistCompareLogger::pin_mismatch, &GenericNetlistCompareLogger::cb_pin_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("pin_mismatch", &GenericNetlistCompareLogger::pin_mismatch, &GenericNetlistCompareLogger::cb_pin_mismatch, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when two pins can't be paired.\n"
|
||||
"This will report the pin considered in a or b. The other argument is nil. "
|
||||
"See \\match_pins for details.\n"
|
||||
|
|
@ -429,7 +429,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
|
|||
"If two subcircuits are identified as a corresponding pair, this method will be called with both subcircuits.\n"
|
||||
"If subcircuits can't be matched, \\subcircuit_mismatch will be called with the one subcircuit considered and the other subcircuit being nil."
|
||||
) +
|
||||
gsi::callback ("subcircuit_mismatch", &GenericNetlistCompareLogger::subcircuit_mismatch, &GenericNetlistCompareLogger::cb_subcircuit_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
gsi::callback ("subcircuit_mismatch", &GenericNetlistCompareLogger::subcircuit_mismatch, &GenericNetlistCompareLogger::cb_subcircuit_mismatch, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("msg"),
|
||||
"@brief This function is called when two subcircuits can't be paired.\n"
|
||||
"This will report the subcircuit considered in a or b. The other argument is nil. "
|
||||
"See \\match_subcircuits for details.\n"
|
||||
|
|
|
|||
|
|
@ -610,15 +610,53 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other,
|
|||
);
|
||||
}
|
||||
|
||||
static inline std::vector<db::Region> as_2region_vector (const std::pair<db::Region, db::Region> &rp)
|
||||
{
|
||||
std::vector<db::Region> res;
|
||||
res.reserve (2);
|
||||
res.push_back (db::Region (const_cast<db::Region &> (rp.first).take_delegate ()));
|
||||
res.push_back (db::Region (const_cast<db::Region &> (rp.second).take_delegate ()));
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other)
|
||||
{
|
||||
std::pair<db::Region, db::Region> rp = r->andnot (other);
|
||||
return as_2region_vector (r->andnot (other));
|
||||
}
|
||||
|
||||
std::vector<db::Region> res;
|
||||
res.resize (2, db::Region ());
|
||||
res [0] = rp.first;
|
||||
res [1] = rp.second;
|
||||
return res;
|
||||
static std::vector<db::Region> split_inside (const db::Region *r, const db::Region &other)
|
||||
{
|
||||
return as_2region_vector (r->selected_inside_differential (other));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_outside (const db::Region *r, const db::Region &other)
|
||||
{
|
||||
return as_2region_vector (r->selected_outside_differential (other));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_overlapping (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2region_vector (r->selected_overlapping_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_covering (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2region_vector (r->selected_enclosing_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_interacting_with_region (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_interacting_with_edges (const db::Region *r, const db::Edges &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_interacting_with_texts (const db::Region *r, const db::Texts &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
|
|
@ -681,6 +719,7 @@ int po_any ();
|
|||
|
||||
extern Class<db::ShapeCollection> decl_dbShapeCollection;
|
||||
|
||||
|
||||
Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||
constructor ("new", &new_v,
|
||||
"@brief Default constructor\n"
|
||||
|
|
@ -903,7 +942,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"polygons which have the given perimeter are returned. If \"inverse\" is true, "
|
||||
"polygons not having the given perimeter are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_perimeter", with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by perimeter\n"
|
||||
|
|
@ -915,7 +954,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by area\n"
|
||||
|
|
@ -923,7 +962,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"polygons which have the given area are returned. If \"inverse\" is true, "
|
||||
"polygons not having the given area are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by area\n"
|
||||
|
|
@ -935,7 +974,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_holes", with_holes1, gsi::arg ("nholes"), gsi::arg ("inverse"),
|
||||
"@brief Filters the polygons by their number of holes\n"
|
||||
|
|
@ -943,7 +982,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"polygons which have the given number of holes are returned. If \"inverse\" is true, "
|
||||
"polygons not having the given of holes are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -957,7 +996,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -967,7 +1006,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"polygons whose bounding box has the given width are returned. If \"inverse\" is true, "
|
||||
"polygons whose bounding box does not have the given width are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_width", with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width\n"
|
||||
|
|
@ -977,7 +1016,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_height", with_bbox_height1, gsi::arg ("height"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box height\n"
|
||||
|
|
@ -985,7 +1024,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"polygons whose bounding box has the given height are returned. If \"inverse\" is true, "
|
||||
"polygons whose bounding box does not have the given height are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_height", with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box height\n"
|
||||
|
|
@ -995,7 +1034,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_min", with_bbox_min1, gsi::arg ("dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is smaller\n"
|
||||
|
|
@ -1004,7 +1043,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"are returned. "
|
||||
"If \"inverse\" is true, all polygons not matching this criterion are returned."
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_min", with_bbox_min2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is smaller\n"
|
||||
|
|
@ -1015,7 +1054,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_max", with_bbox_max1, gsi::arg ("dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is larger\n"
|
||||
|
|
@ -1024,7 +1063,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"are returned. "
|
||||
"If \"inverse\" is true, all polygons not matching this criterion are returned."
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_max", with_bbox_max2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is larger\n"
|
||||
|
|
@ -1035,7 +1074,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_aspect_ratio", with_bbox_aspect_ratio1, gsi::arg ("ratio"), gsi::arg ("inverse"),
|
||||
"@brief Filters the polygons by the aspect ratio of their bounding boxes\n"
|
||||
|
|
@ -1046,7 +1085,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"With 'inverse' set to false, this version filters polygons which have a bounding box aspect ratio equal to the given value. "
|
||||
"With 'inverse' set to true, all other polygons will be returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1062,7 +1101,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1075,7 +1114,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"With 'inverse' set to false, this version filters polygons which have an area ratio equal to the given value. "
|
||||
"With 'inverse' set to true, all other polygons will be returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1091,7 +1130,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1105,7 +1144,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"With 'inverse' set to false, this version filters polygons which have a relative height equal to the given value. "
|
||||
"With 'inverse' set to true, all other polygons will be returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1122,7 +1161,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1130,7 +1169,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@brief Returns a region containing those parts of polygons which are \"strange\"\n"
|
||||
"Strange parts of polygons are self-overlapping parts or non-orientable parts (i.e. in the \"8\" configuration).\n"
|
||||
"\n"
|
||||
"Merged semantics does not apply for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics does not apply for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("snapped", &db::Region::snapped, gsi::arg ("gx"), gsi::arg ("gy"),
|
||||
"@brief Returns the snapped region\n"
|
||||
|
|
@ -1143,7 +1182,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If gx or gy is 0, no snapping happens in that direction.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("scaled_and_snapped", &db::Region::scaled_and_snapped, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"),
|
||||
"@brief Returns the scaled and snapped region\n"
|
||||
|
|
@ -1159,7 +1198,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If gx or gy is 0, the result is brought on a grid of 1.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1."
|
||||
) +
|
||||
|
|
@ -1171,7 +1210,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If gx or gy is 0 or less, the grid is not checked in that direction.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_angle", angle_check1, gsi::arg ("angle"), gsi::arg ("inverse"),
|
||||
"@brief Returns markers on every corner with the given angle (or not with the given angle)\n"
|
||||
|
|
@ -1181,7 +1220,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"The edge pair objects returned will contain both edges forming the angle.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("with_angle", angle_check2, gsi::arg ("amin"), gsi::arg ("amax"), gsi::arg ("inverse"),
|
||||
"@brief Returns markers on every corner with an angle of more than amin and less than amax (or the opposite)\n"
|
||||
|
|
@ -1191,7 +1230,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"The edge pair objects returned will contain both edges forming the angle.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("insert", (void (db::Region::*)(const db::Box &)) &db::Region::insert, gsi::arg ("box"),
|
||||
"@brief Inserts a box\n"
|
||||
|
|
@ -1266,7 +1305,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
"of these boxes for example.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("extents", &extents1, gsi::arg ("d"),
|
||||
"@brief Returns a region with the enlarged bounding boxes of the polygons\n"
|
||||
|
|
@ -1275,7 +1314,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
"of these boxes for example.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("extents", &extents2, gsi::arg ("dx"), gsi::arg ("dy"),
|
||||
"@brief Returns a region with the enlarged bounding boxes of the polygons\n"
|
||||
|
|
@ -1284,7 +1323,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
"of these boxes for example.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("extent_refs", &extent_refs,
|
||||
"@hide\n"
|
||||
|
|
@ -1446,7 +1485,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"The mode defines at which bending angle cutoff occurs \n"
|
||||
"(0:>0, 1:>45, 2:>90, 3:>135, 4:>approx. 168, other:>approx. 179)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The result is a set of polygons which may be overlapping, but are not self-\n"
|
||||
"intersecting. Polygons may overlap afterwards because they grew big enough to overlap their neighbors.\n"
|
||||
|
|
@ -1468,7 +1507,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"size(d, d, mode)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("size", size_ext, gsi::arg ("d"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
|
|
@ -1477,7 +1516,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"size(d, d, 2)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"),
|
||||
"@brief Returns the anisotropically sized region\n"
|
||||
|
|
@ -1486,7 +1525,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
"@brief Returns the isotropically sized region\n"
|
||||
|
|
@ -1495,7 +1534,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("sized", sized_ext, gsi::arg ("d"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
|
|
@ -1504,7 +1543,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"sized(d, d, 2)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("andnot", &andnot, gsi::arg ("other"),
|
||||
"@brief Returns the boolean AND and NOT between self and the other region\n"
|
||||
|
|
@ -1601,7 +1640,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons which are covering polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
|
|
@ -1612,18 +1651,28 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons which are not covering polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method_ext ("split_covering", &split_covering, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which are completely covering polygons from the other region and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\covering, the second the result of \\not_covering\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\covering and \\not_covering, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_covering", &db::Region::select_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons of this region which are completely covering polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
|
|
@ -1634,7 +1683,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
|
|
@ -1645,56 +1694,76 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons which are inside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("not_inside", &db::Region::selected_not_inside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are not completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons which are not inside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("split_inside", &split_inside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are completely inside polygons from the other region and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\inside, the second the result of \\not_inside\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\inside and \\not_inside, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_inside", &db::Region::select_inside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("select_not_inside", &db::Region::select_not_inside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are not completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("outside", &db::Region::selected_outside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons which are outside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("not_outside", &db::Region::selected_not_outside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are not completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons which are not outside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("split_outside", &split_outside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are completely outside polygons from the other region and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\outside, the second the result of \\not_outside\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\outside and \\not_outside, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_outside", &db::Region::select_outside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("select_not_outside", &db::Region::select_not_outside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are not completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Region &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which overlap or touch polygons from the other region\n"
|
||||
|
|
@ -1706,7 +1775,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1720,10 +1789,20 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("split_interacting", &split_interacting_with_region, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which are interacting with polygons from the other region and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
|
|
@ -1734,7 +1813,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1748,7 +1827,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
|
|
@ -1762,7 +1841,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching edges from the edge collection\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
|
|
@ -1777,11 +1856,21 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching edges from the edge collection\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("split_interacting", &split_interacting_with_edges, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which are interacting with edges from the other edge collection and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
|
|
@ -1792,7 +1881,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
|
|
@ -1807,7 +1896,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
|
|
@ -1822,7 +1911,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching texts\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1836,10 +1925,20 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching texts\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
method_ext ("split_interacting", &split_interacting_with_texts, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which are interacting with texts from the other text collection and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Texts &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons of this region which overlap or touch texts\n"
|
||||
"\n"
|
||||
|
|
@ -1850,7 +1949,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"selected by this method if the number of texts interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1864,7 +1963,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1873,7 +1972,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons overlapping polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -1882,16 +1981,26 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
method_ext ("split_overlapping", &split_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which are overlapping with polygons from the other region and the ones which are not at the same time\n"
|
||||
"\n"
|
||||
"@return Two new regions: the first containing the result of \\overlapping, the second the result of \\not_overlapping\n"
|
||||
"\n"
|
||||
"This method is equivalent to calling \\overlapping and \\not_overlapping, but is faster when both results are required.\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which overlap polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -1900,7 +2009,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -1913,7 +2022,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
|
|
@ -1923,7 +2032,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
|
|
@ -1933,7 +2042,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
|
|
@ -1943,7 +2052,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The edge collection after the edges have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
|
|
@ -1953,7 +2062,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The text collection after the texts have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1974,7 +2083,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"The edge collection returned can be manipulated in various ways. See \\Edges for a description of the "
|
||||
"possibilities of the edge collection.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
factory_ext ("decompose_convex", &decompose_convex<db::Shapes>, gsi::arg ("preferred_orientation", po_any (), "\\Polygon#PO_any"),
|
||||
"@brief Decomposes the region into convex pieces.\n"
|
||||
|
|
@ -2018,7 +2127,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@brief Returns the holes of the region\n"
|
||||
"This method returns all holes as filled polygons.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"If merge semantics is not enabled, the holes may not be detected if the polygons "
|
||||
"are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) "
|
||||
"in order to merge the polygons and detect holes.\n"
|
||||
|
|
@ -2027,7 +2136,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@brief Returns the hulls of the region\n"
|
||||
"This method returns all hulls as polygons. The holes will be removed (filles). "
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"If merge semantics is not enabled, the hull may also enclose holes if the polygons "
|
||||
"are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) "
|
||||
"in order to merge the polygons and detect holes.\n"
|
||||
|
|
@ -2045,36 +2154,36 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
method_ext ("rectangles", &rectangles,
|
||||
"@brief Returns all polygons which are rectangles\n"
|
||||
"This method returns all polygons in self which are rectangles."
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("non_rectangles", &non_rectangles,
|
||||
"@brief Returns all polygons which are not rectangles\n"
|
||||
"This method returns all polygons in self which are not rectangles."
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("squares", &squares,
|
||||
"@brief Returns all polygons which are squares\n"
|
||||
"This method returns all polygons in self which are squares."
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("non_squares", &non_squares,
|
||||
"@brief Returns all polygons which are not squares\n"
|
||||
"This method returns all polygons in self which are not squares."
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("rectilinear", &rectilinear,
|
||||
"@brief Returns all polygons which are rectilinear\n"
|
||||
"This method returns all polygons in self which are rectilinear."
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("non_rectilinear", &non_rectilinear,
|
||||
"@brief Returns all polygons which are not rectilinear\n"
|
||||
"This method returns all polygons in self which are not rectilinear."
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("break", &break_polygons, gsi::arg ("max_vertex_count"), gsi::arg ("max_area_ratio", 0.0),
|
||||
"@brief Breaks the polygons of the region into smaller ones\n"
|
||||
|
|
@ -2103,7 +2212,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"with a pencil that has the shape of the given region.\n"
|
||||
"\n"
|
||||
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("minkowsky_sum", &minkowsky_sum_pp, gsi::arg ("p"),
|
||||
"@brief Compute the Minkowsky sum of the region and a polygon\n"
|
||||
|
|
@ -2116,7 +2225,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"the region with a pen that has the shape of the second polygon.\n"
|
||||
"\n"
|
||||
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("minkowsky_sum", &minkowsky_sum_pb, gsi::arg ("b"),
|
||||
"@brief Compute the Minkowsky sum of the region and a box\n"
|
||||
|
|
@ -2129,7 +2238,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"as the second polygon.\n"
|
||||
"\n"
|
||||
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("minkowsky_sum", &minkowsky_sum_pc, gsi::arg ("b"),
|
||||
"@brief Compute the Minkowsky sum of the region and a contour of points (a trace)\n"
|
||||
|
|
@ -2143,7 +2252,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"with a pencil that has the shape of the given region.\n"
|
||||
"\n"
|
||||
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("move", &move_p, gsi::arg ("v"),
|
||||
"@brief Moves the region\n"
|
||||
|
|
@ -2268,7 +2377,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to "
|
||||
"false. In general, this will improve performance somewhat.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded' and 'negative' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2310,7 +2419,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2351,7 +2460,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to "
|
||||
"false. In general, this will improve performance somewhat.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded' and 'negative' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2393,7 +2502,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2436,7 +2545,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2479,7 +2588,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2522,7 +2631,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -2565,27 +2674,27 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
method_ext ("area", &area1,
|
||||
"@brief The area of the region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"If merged semantics is not enabled, overlapping areas are counted twice.\n"
|
||||
) +
|
||||
method_ext ("area", &area2, gsi::arg ("rect"),
|
||||
"@brief The area of the region (restricted to a rectangle)\n"
|
||||
"This version will compute the area of the shapes, restricting the computation to the given rectangle.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"If merged semantics is not enabled, overlapping areas are counted twice.\n"
|
||||
) +
|
||||
method_ext ("perimeter", &perimeter1,
|
||||
"@brief The total perimeter of the polygons\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"If merged semantics is not enabled, internal edges are counted as well.\n"
|
||||
) +
|
||||
method_ext ("perimeter", &perimeter2, gsi::arg ("rect"),
|
||||
|
|
@ -2594,7 +2703,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"Edges along the border are handled in a special way: they are counted when they are oriented with their inside "
|
||||
"side toward the rectangle (in other words: outside edges must coincide with the rectangle's border in order to be counted).\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"If merged semantics is not enabled, internal edges are counted as well.\n"
|
||||
) +
|
||||
method ("bbox", &db::Region::bbox,
|
||||
|
|
|
|||
|
|
@ -44,22 +44,22 @@ public:
|
|||
out ("begin_circuit " + circuit2str (a) + " " + circuit2str (b));
|
||||
}
|
||||
|
||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching)
|
||||
virtual void end_circuit (const db::Circuit *a, const db::Circuit *b, bool matching, const std::string & /*msg*/)
|
||||
{
|
||||
out ("end_circuit " + circuit2str (a) + " " + circuit2str (b) + " " + (matching ? "MATCH" : "NOMATCH"));
|
||||
}
|
||||
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_skipped (const db::Circuit *a, const db::Circuit *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("circuit_skipped " + circuit2str (a) + " " + circuit2str (b));
|
||||
}
|
||||
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b)
|
||||
virtual void circuit_mismatch (const db::Circuit *a, const db::Circuit *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("circuit_mismatch " + circuit2str (a) + " " + circuit2str (b));
|
||||
}
|
||||
|
||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b)
|
||||
virtual void device_class_mismatch (const db::DeviceClass *a, const db::DeviceClass *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("device_class_mismatch " + dc2str (a) + " " + dc2str (b));
|
||||
}
|
||||
|
|
@ -69,12 +69,12 @@ public:
|
|||
out ("match_nets " + net2str (a) + " " + net2str (b));
|
||||
}
|
||||
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b)
|
||||
virtual void match_ambiguous_nets (const db::Net *a, const db::Net *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("match_ambiguous_nets " + net2str (a) + " " + net2str (b));
|
||||
}
|
||||
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b)
|
||||
virtual void net_mismatch (const db::Net *a, const db::Net *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("net_mismatch " + net2str (a) + " " + net2str (b));
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ public:
|
|||
out ("match_devices " + device2str (a) + " " + device2str (b));
|
||||
}
|
||||
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b)
|
||||
virtual void device_mismatch (const db::Device *a, const db::Device *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("device_mismatch " + device2str (a) + " " + device2str (b));
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ public:
|
|||
out ("match_pins " + pin2str (a) + " " + pin2str (b));
|
||||
}
|
||||
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b)
|
||||
virtual void pin_mismatch (const db::Pin *a, const db::Pin *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("pin_mismatch " + pin2str (a) + " " + pin2str (b));
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ public:
|
|||
out ("match_subcircuits " + subcircuit2str (a) + " " + subcircuit2str (b));
|
||||
}
|
||||
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b)
|
||||
virtual void subcircuit_mismatch (const db::SubCircuit *a, const db::SubCircuit *b, const std::string & /*msg*/)
|
||||
{
|
||||
out ("subcircuit_mismatch " + subcircuit2str (a) + " " + subcircuit2str (b));
|
||||
}
|
||||
|
|
@ -954,7 +954,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
EXPECT_EQ (good, false);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.5, 0.0));
|
||||
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.5, 0.0));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
|
|
@ -980,7 +980,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
EXPECT_EQ (good, true);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.0));
|
||||
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.0));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
|
|
@ -1006,7 +1006,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
EXPECT_EQ (good, false);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.2));
|
||||
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.2));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
|
|
@ -1032,7 +1032,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
EXPECT_EQ (good, false);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.4));
|
||||
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.4));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
|
|
@ -1059,7 +1059,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
|
||||
logger.clear ();
|
||||
db::EqualDeviceParameters eq_dp = db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W) + db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.2, 0.0);
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (eq_dp));
|
||||
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (eq_dp));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
|
|
@ -1086,7 +1086,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
|
||||
logger.clear ();
|
||||
eq_dp = db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W) + db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L);
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (eq_dp));
|
||||
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (eq_dp));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
|
|
|
|||
|
|
@ -354,6 +354,8 @@ TEST(10a)
|
|||
r.set_merged_semantics (false);
|
||||
EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_not_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).first.to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (db::compare (r.selected_interacting (db::Region (db::Box (db::Point (-20, -20), db::Point (30, 30)))), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
|
||||
EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
db::Region rr = r;
|
||||
|
|
@ -836,6 +838,8 @@ TEST(18a)
|
|||
EXPECT_EQ (db::compare (o, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
|
||||
o = r;
|
||||
EXPECT_EQ (db::compare (o.selected_not_outside (rr), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_outside_differential (rr).first, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_outside_differential (rr).second, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (o.selected_outside (rr).count () + o.selected_not_outside (rr).count (), size_t (6));
|
||||
EXPECT_EQ (o.selected_outside (rr).hier_count () + o.selected_not_outside (rr).hier_count (), size_t (6));
|
||||
o.select_not_outside (rr);
|
||||
|
|
@ -848,6 +852,8 @@ TEST(18a)
|
|||
EXPECT_EQ (o.to_string (), "(20,30;20,50;40,50;40,30)");
|
||||
o = r;
|
||||
EXPECT_EQ (db::compare (o.selected_not_inside (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_inside_differential (rr).first, "(20,30;20,50;40,50;40,30)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_inside_differential (rr).second, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (o.selected_inside (rr).count () + o.selected_not_inside (rr).count (), size_t (6));
|
||||
EXPECT_EQ (o.selected_inside (rr).hier_count () + o.selected_not_inside (rr).hier_count (), size_t (6));
|
||||
o.select_not_inside (rr);
|
||||
|
|
@ -860,6 +866,8 @@ TEST(18a)
|
|||
EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
o = r;
|
||||
EXPECT_EQ (o.selected_not_interacting (rr).to_string (), "(70,60;70,80;90,80;90,60)");
|
||||
EXPECT_EQ (db::compare (o.selected_interacting_differential (rr).first, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_interacting_differential (rr).second, "(70,60;70,80;90,80;90,60)"), true);
|
||||
EXPECT_EQ (o.selected_interacting (rr).count () + o.selected_not_interacting (rr).count (), size_t (6));
|
||||
EXPECT_EQ (o.selected_interacting (rr).hier_count () + o.selected_not_interacting (rr).hier_count (), size_t (6));
|
||||
o.select_not_interacting (rr);
|
||||
|
|
@ -872,6 +880,8 @@ TEST(18a)
|
|||
EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
o = r;
|
||||
EXPECT_EQ (db::compare (o.selected_not_overlapping (rr), "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_overlapping_differential (rr).first, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_overlapping_differential (rr).second, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
|
||||
EXPECT_EQ (o.selected_overlapping (rr).count () + o.selected_not_overlapping (rr).count (), size_t (6));
|
||||
EXPECT_EQ (o.selected_overlapping (rr).hier_count () + o.selected_not_overlapping (rr).hier_count (), size_t (6));
|
||||
o.select_not_overlapping (rr);
|
||||
|
|
@ -884,6 +894,8 @@ TEST(18a)
|
|||
EXPECT_EQ (o.to_string (), "(0,100;0,130;30,130;30,100)");
|
||||
o = r;
|
||||
EXPECT_EQ (db::compare (o.selected_not_enclosing (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_enclosing_differential (rr).first, "(0,100;0,130;30,130;30,100)"), true);
|
||||
EXPECT_EQ (db::compare (o.selected_enclosing_differential (rr).second, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true);
|
||||
EXPECT_EQ (o.selected_enclosing (rr).count () + o.selected_not_enclosing (rr).count (), size_t (6));
|
||||
EXPECT_EQ (o.selected_enclosing (rr).hier_count () + o.selected_not_enclosing (rr).hier_count (), size_t (6));
|
||||
o.select_not_enclosing (rr);
|
||||
|
|
@ -1506,6 +1518,8 @@ TEST(30a)
|
|||
r.set_merged_semantics (false);
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_not_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).first.to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (db::compare (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)"), true);
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
db::Region rr = r;
|
||||
|
|
@ -1689,6 +1703,8 @@ TEST(34a)
|
|||
r.set_merged_semantics (false);
|
||||
EXPECT_EQ (r.selected_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_not_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).first.to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
db::Texts tt;
|
||||
tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30))));
|
||||
tt.insert (db::Text ("xyz", db::Trans (db::Vector (-100, 0))));
|
||||
|
|
@ -1782,6 +1798,7 @@ TEST(35a_interact_with_count_region)
|
|||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
|
@ -1797,6 +1814,7 @@ TEST(35a_interact_with_count_region)
|
|||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
|
||||
|
|
@ -1855,6 +1873,7 @@ TEST(35b_interact_with_count_edge)
|
|||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (rr, 2, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
|
@ -1869,6 +1888,7 @@ TEST(35b_interact_with_count_edge)
|
|||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
|
||||
|
|
@ -1926,6 +1946,7 @@ TEST(35c_interact_with_count_text)
|
|||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (rr, 2, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
|
@ -1940,6 +1961,7 @@ TEST(35c_interact_with_count_text)
|
|||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ module DRC
|
|||
@deep = false
|
||||
@netter = nil
|
||||
@netter_data = nil
|
||||
@total_timer = nil
|
||||
@drc_progress = nil
|
||||
|
||||
# initialize the defaults for max_area_ratio, max_vertex_count
|
||||
dss = RBA::DeepShapeStore::new
|
||||
|
|
@ -58,7 +60,7 @@ module DRC
|
|||
|
||||
@verbose = false
|
||||
|
||||
@in_context = false
|
||||
@in_context = nil
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -93,7 +95,7 @@ module DRC
|
|||
def transparent
|
||||
DRCShielded::new(false)
|
||||
end
|
||||
|
||||
|
||||
def projection_limits(*args)
|
||||
self._context("projection_limits") do
|
||||
if args.size == 0
|
||||
|
|
@ -211,6 +213,27 @@ module DRC
|
|||
end
|
||||
end
|
||||
|
||||
def tile_size(x, y = nil)
|
||||
DRCTileSize::new(_make_value(x) * self.dbu, _make_value(y || x) * self.dbu)
|
||||
end
|
||||
|
||||
def tile_step(x, y = nil)
|
||||
DRCTileStep::new(_make_value(x) * self.dbu, _make_value(y || x) * self.dbu)
|
||||
end
|
||||
|
||||
def tile_origin(x, y)
|
||||
DRCTileOrigin::new(_make_value(x) * self.dbu, _make_value(y) * self.dbu)
|
||||
end
|
||||
|
||||
def tile_count(x, y)
|
||||
DRCTileCount::new(_make_numeric_value(x), _make_numeric_value(y))
|
||||
end
|
||||
|
||||
def tile_boundary(b)
|
||||
b.is_a?(DRCLayer) || raise("'tile_boundary' requires a layer argument")
|
||||
DRCTileBoundary::new(b)
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @brief Defines SPICE output format (with options)
|
||||
# @name write_spice
|
||||
|
|
@ -455,15 +478,20 @@ module DRC
|
|||
|
||||
# %DRC%
|
||||
# @name info
|
||||
# @brief Outputs as message to the logger window
|
||||
# @brief Outputs as message to the logger or progress window
|
||||
# @synopsis info(message)
|
||||
# @synopsis info(message, indent)
|
||||
# Prints the message to the log window in verbose mode.
|
||||
# In non-verbose more, nothing is printed.
|
||||
# In non-verbose more, nothing is printed but a statement is put into the progress window.
|
||||
# \log is a function that always prints a message.
|
||||
|
||||
def info(arg, indent = 0)
|
||||
@verbose && log(arg, indent)
|
||||
if @verbose
|
||||
log(arg, indent)
|
||||
else
|
||||
str = (" " * indent) + arg
|
||||
RBA::Logger::log(str)
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
|
|
@ -476,7 +504,7 @@ module DRC
|
|||
# verbose mode is enabled.
|
||||
|
||||
def log(arg, indent = 0)
|
||||
str = (" " * indent) + arg
|
||||
str = (" " * indent) + arg
|
||||
if @log_file
|
||||
@log_file.puts(str)
|
||||
else
|
||||
|
|
@ -1828,9 +1856,10 @@ CODE
|
|||
def _wrapper_context(func, *args, &proc)
|
||||
in_context_outer = @in_context
|
||||
begin
|
||||
@in_context = true
|
||||
@in_context = func
|
||||
return yield(*args)
|
||||
rescue => ex
|
||||
RBA::MacroExecutionContext::ignore_next_exception
|
||||
raise("'" + func + "': " + ex.to_s)
|
||||
ensure
|
||||
@in_context = in_context_outer
|
||||
|
|
@ -1842,22 +1871,41 @@ CODE
|
|||
return yield(*args)
|
||||
else
|
||||
begin
|
||||
@in_context = true
|
||||
@in_context = func
|
||||
return yield(*args)
|
||||
rescue => ex
|
||||
RBA::MacroExecutionContext::ignore_next_exception
|
||||
raise("'" + func + "': " + ex.to_s)
|
||||
ensure
|
||||
@in_context = false
|
||||
@in_context = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def _result_info(res, indent, prefix = "")
|
||||
if res.is_a?(Array)
|
||||
res.each_with_index do |a, index|
|
||||
_result_info(a, indent, "[#{index + 1}] ")
|
||||
end
|
||||
elsif res.is_a?(RBA::Region)
|
||||
info(prefix + "Polygons (raw): #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
|
||||
elsif res.is_a?(RBA::Edges)
|
||||
info(prefix + "Edges: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
|
||||
elsif res.is_a?(RBA::EdgePairs)
|
||||
info(prefix + "Edge pairs: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
|
||||
elsif res.is_a?(RBA::Texts)
|
||||
info(prefix + "Texts: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
|
||||
end
|
||||
end
|
||||
|
||||
def run_timed(desc, obj)
|
||||
|
||||
log(desc)
|
||||
info(desc)
|
||||
|
||||
# enable progress
|
||||
disable_progress = false
|
||||
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
|
||||
disable_progress = true
|
||||
obj.enable_progress(desc)
|
||||
end
|
||||
|
||||
|
|
@ -1867,39 +1915,37 @@ CODE
|
|||
res = yield
|
||||
t.stop
|
||||
|
||||
if @verbose
|
||||
begin
|
||||
|
||||
if @verbose
|
||||
|
||||
# Report result statistics
|
||||
_result_info(res, 1)
|
||||
|
||||
mem = RBA::Timer::memory_size
|
||||
if mem > 0
|
||||
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M", 1)
|
||||
else
|
||||
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s", 1)
|
||||
end
|
||||
|
||||
# Report result statistics
|
||||
if res.is_a?(RBA::Region)
|
||||
info("Polygons (raw): #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
|
||||
elsif res.is_a?(RBA::Edges)
|
||||
info("Edges: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
|
||||
elsif res.is_a?(RBA::EdgePairs)
|
||||
info("Edge pairs: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
|
||||
elsif res.is_a?(RBA::Texts)
|
||||
info("Texts: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
|
||||
end
|
||||
|
||||
mem = RBA::Timer::memory_size
|
||||
if mem > 0
|
||||
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M", 1)
|
||||
else
|
||||
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s", 1)
|
||||
ensure
|
||||
|
||||
# disable progress again
|
||||
if disable_progress
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress
|
||||
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
||||
def _cmd(obj, method, *args)
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
obj.send(method, *args)
|
||||
end
|
||||
end
|
||||
|
|
@ -1929,8 +1975,9 @@ CODE
|
|||
end
|
||||
av = args.size.times.collect { |i| "a#{i}" }.join(", ")
|
||||
tp.queue("_output(res, self.#{method}(#{av}))")
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
tp.execute("Tiled \"#{method}\" in: #{src_line}")
|
||||
res
|
||||
end
|
||||
|
||||
else
|
||||
|
|
@ -1940,17 +1987,12 @@ CODE
|
|||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method, *args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress again
|
||||
if obj.is_a?(RBA::Region)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
|
@ -1984,8 +2026,9 @@ CODE
|
|||
end
|
||||
av = args.size.times.collect { |i| "a#{i}" }.join(", ")
|
||||
tp.queue("var rr = self.#{method}(#{av}); _output(res1, rr[0]); _output(res2, rr[1])")
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
tp.execute("Tiled \"#{method}\" in: #{src_line}")
|
||||
res
|
||||
end
|
||||
|
||||
else
|
||||
|
|
@ -1995,17 +2038,12 @@ CODE
|
|||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method, *args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress again
|
||||
if obj.is_a?(RBA::Region)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
|
@ -2025,8 +2063,9 @@ CODE
|
|||
tp.input("self", obj)
|
||||
tp.threads = (@tt || 1)
|
||||
tp.queue("_output(res, _tile ? self.#{method}(_tile.bbox) : self.#{method})")
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
tp.execute("Tiled \"#{method}\" in: #{src_line}")
|
||||
res
|
||||
end
|
||||
|
||||
res = res.value
|
||||
|
|
@ -2038,39 +2077,39 @@ CODE
|
|||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress again
|
||||
if obj.is_a?(RBA::Region)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
||||
def _rcmd(obj, method, *args)
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
RBA::Region::new(obj.send(method, *args))
|
||||
end
|
||||
end
|
||||
|
||||
def _vcmd(obj, method, *args)
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
obj.send(method, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def _start
|
||||
def _start(job_description)
|
||||
|
||||
# clearing the selection avoids some nasty problems
|
||||
view = RBA::LayoutView::current
|
||||
view && view.cancel
|
||||
|
||||
@total_timer = RBA::Timer::new
|
||||
@total_timer.start
|
||||
|
||||
@drc_progress = RBA::AbstractProgress::new(job_description)
|
||||
|
||||
end
|
||||
|
||||
def _flush
|
||||
|
|
@ -2210,9 +2249,20 @@ CODE
|
|||
@netter = nil
|
||||
@netter_data = nil
|
||||
|
||||
if final && @log_file
|
||||
@log_file.close
|
||||
@log_file = nil
|
||||
if final
|
||||
|
||||
@total_timer.stop
|
||||
if @verbose
|
||||
mem = RBA::Timer::memory_size
|
||||
if mem > 0
|
||||
info("Total elapsed: #{'%.3f'%(@total_timer.sys+@total_timer.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M")
|
||||
else
|
||||
info("Total elapsed: #{'%.3f'%(@total_timer.sys+@total_timer.user)}s")
|
||||
end
|
||||
end
|
||||
|
||||
_cleanup
|
||||
|
||||
end
|
||||
|
||||
# force garbage collection
|
||||
|
|
@ -2222,6 +2272,23 @@ CODE
|
|||
|
||||
end
|
||||
|
||||
def _cleanup
|
||||
|
||||
if @log_file
|
||||
@log_file.close
|
||||
@log_file = nil
|
||||
end
|
||||
|
||||
# unlocks the UI
|
||||
if @drc_progress
|
||||
@drc_progress._destroy
|
||||
@drc_progress = nil
|
||||
end
|
||||
|
||||
GC.start
|
||||
|
||||
end
|
||||
|
||||
def _take_data
|
||||
|
||||
if ! @netter
|
||||
|
|
@ -2526,6 +2593,9 @@ CODE
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
data
|
||||
|
||||
end
|
||||
|
||||
def make_source(layout, cell = nil, path = nil)
|
||||
|
|
|
|||
|
|
@ -983,8 +983,8 @@ CODE
|
|||
# @name corners
|
||||
# @brief Selects corners of polygons
|
||||
# @synopsis layer.corners([ options ])
|
||||
# @synopsis layer.corners(angle, [ options ])
|
||||
# @synopsis layer.corners(amin .. amax, [ options ])
|
||||
# @synopsis layer.corners(angle [, options ])
|
||||
# @synopsis layer.corners(amin .. amax [, options ])
|
||||
#
|
||||
# This method produces markers on the corners of the polygons. An angle criterion can be given which
|
||||
# selects corners based on the angle of the connecting edges. Positive angles indicate a left turn
|
||||
|
|
@ -1263,6 +1263,7 @@ CODE
|
|||
self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
|
||||
block.call(object.transformed(t)) && new_data.insert(object)
|
||||
end
|
||||
new_data
|
||||
end
|
||||
DRCLayer::new(@engine, new_data)
|
||||
|
||||
|
|
@ -1285,7 +1286,7 @@ CODE
|
|||
@engine._wrapper_context("each") do
|
||||
|
||||
t = RBA::CplxTrans::new(@engine.dbu)
|
||||
@engine.run_timed("\"select\" in: #{@engine.src_line}", self.data) do
|
||||
@engine.run_timed("\"each\" in: #{@engine.src_line}", self.data) do
|
||||
self.data.send(self.data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
|
||||
block.call(object.transformed(t))
|
||||
end
|
||||
|
|
@ -1368,10 +1369,11 @@ CODE
|
|||
t = RBA::CplxTrans::new(@engine.dbu)
|
||||
dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu)
|
||||
|
||||
@engine.run_timed("\\"select\\" in: " + @engine.src_line, self.data) do
|
||||
@engine.run_timed("\\"#{f}\\" in: " + @engine.src_line, self.data) do
|
||||
self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
|
||||
insert_object_into(new_data, block.call(object.transformed(t)), dbu_trans)
|
||||
end
|
||||
new_data
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, new_data)
|
||||
|
|
@ -1660,6 +1662,7 @@ CODE
|
|||
|
||||
@engine._context("andnot") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_region
|
||||
other.requires_region
|
||||
|
||||
|
|
@ -1773,6 +1776,21 @@ CODE
|
|||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_not_covering.
|
||||
|
||||
# %DRC%
|
||||
# @name split_covering
|
||||
# @brief Returns the results of \covering and \not_covering at the same time
|
||||
# @synopsis (a, b) = layer.split_covering(other [, options ])
|
||||
#
|
||||
# This method returns the polygons covering polygons from the other layer in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \covering and \not_covering, but is faster than doing this in separate steps:
|
||||
#
|
||||
# @code
|
||||
# (covering, not_covering) = l1.split_covering(l2)
|
||||
# @/code
|
||||
#
|
||||
# The options of this method are the same than \covering.
|
||||
|
||||
# %DRC%
|
||||
# @name select_covering
|
||||
# @brief Selects shapes or regions of self which completely cover (enclose) one or more shapes from the other region
|
||||
|
|
@ -1849,6 +1867,21 @@ CODE
|
|||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_not_overlapping.
|
||||
|
||||
# %DRC%
|
||||
# @name split_overlapping
|
||||
# @brief Returns the results of \overlapping and \not_overlapping at the same time
|
||||
# @synopsis (a, b) = layer.split_overlapping(other [, options ])
|
||||
#
|
||||
# This method returns the polygons overlapping polygons from the other layer in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \overlapping and \not_overlapping, but is faster than doing this in separate steps:
|
||||
#
|
||||
# @code
|
||||
# (overlapping, not_overlapping) = l1.split_overlapping(l2)
|
||||
# @/code
|
||||
#
|
||||
# The options of this method are the same than \overlapping.
|
||||
|
||||
# %DRC%
|
||||
# @name select_overlapping
|
||||
# @brief Selects shapes or regions of self which overlap shapes from the other region
|
||||
|
|
@ -1923,6 +1956,19 @@ CODE
|
|||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name split_inside
|
||||
# @brief Returns the results of \inside and \not_inside at the same time
|
||||
# @synopsis (a, b) = layer.split_inside(other)
|
||||
#
|
||||
# This method returns the polygons inside of polygons from the other layer in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \inside and \not_inside, but is faster than doing this in separate steps:
|
||||
#
|
||||
# @code
|
||||
# (inside, not_inside) = l1.split_inside(l2)
|
||||
# @/code
|
||||
|
||||
# %DRC%
|
||||
# @name select_inside
|
||||
# @brief Selects shapes or regions of self which are inside the other region
|
||||
|
|
@ -1995,6 +2041,19 @@ CODE
|
|||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name split_outside
|
||||
# @brief Returns the results of \outside and \not_outside at the same time
|
||||
# @synopsis (a, b) = layer.split_outside(other)
|
||||
#
|
||||
# This method returns the polygons outside of polygons from the other layer in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \outside and \not_outside, but is faster than doing this in separate steps:
|
||||
#
|
||||
# @code
|
||||
# (outside, not_outside) = l1.split_outside(l2)
|
||||
# @/code
|
||||
|
||||
# %DRC%
|
||||
# @name select_outside
|
||||
# @brief Selects shapes or regions of self which are outside the other region
|
||||
|
|
@ -2149,6 +2208,21 @@ CODE
|
|||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name split_interacting
|
||||
# @brief Returns the results of \interacting and \not_interacting at the same time
|
||||
# @synopsis (a, b) = layer.split_interacting(other [, options ])
|
||||
#
|
||||
# This method returns the polygons interacting with objects from the other container in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \interacting and \not_interacting, but is faster than doing this in separate steps:
|
||||
#
|
||||
# @code
|
||||
# (interacting, not_interacting) = l1.split_interacting(l2)
|
||||
# @/code
|
||||
#
|
||||
# The options of this method are the same than \interacting.
|
||||
|
||||
# %DRC%
|
||||
# @name select_interacting
|
||||
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region
|
||||
|
|
@ -2192,7 +2266,7 @@ CODE
|
|||
# number of (different) shapes from the other layer. If a min and max count is given, shapes from
|
||||
# self are selected only if they interact with less than min_count or more than max_count different shapes
|
||||
# from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
|
||||
|
||||
|
||||
# %DRC%
|
||||
# @name intersections
|
||||
# @brief Returns the intersection points of intersecting edge segments for two edge collections
|
||||
|
|
@ -2285,6 +2359,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
if :#{f} != :pull_interacting
|
||||
requires_region
|
||||
other.requires_region
|
||||
|
|
@ -2310,11 +2385,16 @@ CODE
|
|||
%w(| ^ inside not_inside outside not_outside in not_in).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_same_type(other)
|
||||
requires_edges_or_region
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2325,12 +2405,14 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
other.requires_edges_texts_or_region
|
||||
if self.data.is_a?(RBA::Texts)
|
||||
other.requires_region
|
||||
else
|
||||
other.requires_edges_or_region
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
|
@ -2342,10 +2424,14 @@ CODE
|
|||
%w(+).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_same_type(other)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2356,7 +2442,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
other.requires_edges_texts_or_region
|
||||
check_is_layer(other)
|
||||
if self.data.is_a?(RBA::Text)
|
||||
other.requires_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
|
|
@ -2381,6 +2467,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_edges_texts_or_region
|
||||
if self.data.is_a?(RBA::Text)
|
||||
other.requires_region
|
||||
|
|
@ -2389,6 +2476,7 @@ CODE
|
|||
else
|
||||
other.requires_edges_or_region
|
||||
end
|
||||
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args))
|
||||
DRCLayer::new(@engine, self.data)
|
||||
|
|
@ -2402,14 +2490,39 @@ CODE
|
|||
CODE
|
||||
end
|
||||
|
||||
%w(overlapping not_overlapping covering not_covering).each do |f|
|
||||
%w(split_interacting).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other, *args)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_region
|
||||
other.requires_edges_texts_or_region
|
||||
|
||||
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args))
|
||||
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(overlapping not_overlapping covering not_covering).each do |f|
|
||||
eval <<"CODE"
|
||||
|
||||
def #{f}(other, *args)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_same_type(other)
|
||||
requires_region
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args)))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2424,6 +2537,7 @@ CODE
|
|||
|
||||
requires_region
|
||||
requires_same_type(other)
|
||||
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args))
|
||||
DRCLayer::new(@engine, self.data)
|
||||
|
|
@ -2437,6 +2551,24 @@ CODE
|
|||
CODE
|
||||
end
|
||||
|
||||
%w(split_overlapping split_covering).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other, *args)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_region
|
||||
other.requires_region
|
||||
|
||||
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args))
|
||||
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(inside not_inside outside not_outside).each do |fi|
|
||||
f = "select_" + fi
|
||||
# In tiled mode, there are no modifying versions. Emulate using the non-modifying one.
|
||||
|
|
@ -2447,6 +2579,7 @@ CODE
|
|||
|
||||
requires_region
|
||||
requires_same_type(other)
|
||||
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data)
|
||||
DRCLayer::new(@engine, self.data)
|
||||
|
|
@ -2460,14 +2593,39 @@ CODE
|
|||
CODE
|
||||
end
|
||||
|
||||
%w(split_inside split_outside).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_region
|
||||
other.requires_region
|
||||
|
||||
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data)
|
||||
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(inside_part outside_part).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
other.requires_region
|
||||
requires_edges
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2475,11 +2633,17 @@ CODE
|
|||
%w(intersections).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
other.requires_edges
|
||||
requires_edges
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -3496,6 +3660,180 @@ CODE
|
|||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name with_density
|
||||
# @brief Returns tiles whose density is within a given range
|
||||
# @synopsis layer.with_density(min_value, max_value [, options ])
|
||||
# @synopsis layer.with_density(min_value .. max_value [, options ])
|
||||
#
|
||||
# This method runs a tiled analysis over the current layout. It reports the tiles whose density
|
||||
# is between "min_value" and "max_value". "min_value" and "max_value" are given in
|
||||
# relative units, i.e. within the range of 0 to 1.0 corresponding to a density of 0 to 100%.
|
||||
#
|
||||
# "min_value" or "max_value" can be nil or omitted in the ".." range notation.
|
||||
# In this case, they are taken as "0" and "100%".
|
||||
#
|
||||
# The tile size must be specified with the "tile_size" option:
|
||||
#
|
||||
# @code
|
||||
# # reports areas where layer 1/0 density is below 10% on 20x20 um tiles
|
||||
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
|
||||
# @/code
|
||||
#
|
||||
# Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
|
||||
# The first value is the horizontal tile dimension, the second value is the vertical tile
|
||||
# dimension.
|
||||
#
|
||||
# A tile overlap can be specified using "tile_step". If the tile step is less than the
|
||||
# tile size, the tiles will overlap. The layout window given by "tile_size" is moved
|
||||
# in increments of the tile step:
|
||||
#
|
||||
# @code
|
||||
# # reports areas where layer 1/0 density is below 10% on 30x30 um tiles
|
||||
# # with a tile step of 20x20 um:
|
||||
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
|
||||
# @/code
|
||||
#
|
||||
# For "tile_step", anisotropic values can be given as well by using two values: the first for the
|
||||
# horizontal and the second for the vertical tile step.
|
||||
#
|
||||
# Another option is "tile_origin" which specifies the location of the first tile's position.
|
||||
# This is the lower left tile's lower left corner. If no origin is given, the tiles are centered over the
|
||||
# area investigated.
|
||||
#
|
||||
# By default, the tiles will cover the bounding box of the input layer. A separate layer
|
||||
# can be used in addition. This way, the layout's dimensions can be derived from some
|
||||
# drawn boundary layer. To specify a separate, additional layer included in the bounding box, use the "tile_boundary" option:
|
||||
#
|
||||
# @code
|
||||
# # reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
|
||||
# # layer 0/0:
|
||||
# cell_frame = input(0, 0)
|
||||
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
|
||||
# @/code
|
||||
#
|
||||
# Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
|
||||
# The computed area is at least the area of the input layer.
|
||||
#
|
||||
# Computation of the area can be skipped by explicitly giving a tile count in horizontal and vertical
|
||||
# direction. With the "tile_origin" option this allows full control over the area covered:
|
||||
#
|
||||
# @code
|
||||
# # reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
|
||||
# # (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
|
||||
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
|
||||
# @/code
|
||||
#
|
||||
# The complementary version of "with_density" is \without_density.
|
||||
|
||||
# %DRC%
|
||||
# @name without_density
|
||||
# @brief Returns tiles whose density is not within a given range
|
||||
# @synopsis layer.without_density(min_value, max_value [, options ])
|
||||
# @synopsis layer.without_density(min_value .. max_value [, options ])
|
||||
#
|
||||
# For details about the operations and the operation see \with_density. This version will return the
|
||||
# tiles where the density is not within the given range.
|
||||
|
||||
def _with_density(method, inverse, *args)
|
||||
|
||||
requires_region
|
||||
|
||||
limits = [ nil, nil ]
|
||||
nlimits = 0
|
||||
tile_size = nil
|
||||
tile_step = nil
|
||||
tile_origin = nil
|
||||
tile_count = nil
|
||||
tile_boundary = nil
|
||||
|
||||
n = 1
|
||||
args.each do |a|
|
||||
if a.is_a?(DRCTileSize)
|
||||
tile_size = a.get
|
||||
elsif a.is_a?(DRCTileStep)
|
||||
tile_step = a.get
|
||||
elsif a.is_a?(DRCTileOrigin)
|
||||
tile_origin = a.get
|
||||
elsif a.is_a?(DRCTileCount)
|
||||
tile_count = a.get
|
||||
elsif a.is_a?(DRCTileBoundary)
|
||||
tile_boundary = a.get
|
||||
elsif a.is_a?(Float) || a.is_a?(1.class) || a == nil
|
||||
nlimits < 2 || raise("Too many values specified")
|
||||
limits[nlimits] = @engine._make_numeric_value_with_nil(a)
|
||||
nlimits += 1
|
||||
elsif a.is_a?(Range)
|
||||
nlimits == 0 || raise("Either a range or two limits have to be specified, not both")
|
||||
limits = [ @engine._make_numeric_value_with_nil(a.begin), @engine._make_numeric_value_with_nil(a.end) ]
|
||||
nlimits = 2
|
||||
else
|
||||
raise("Parameter #" + n.to_s + " does not have an expected type")
|
||||
end
|
||||
n += 1
|
||||
end
|
||||
|
||||
tile_size || raise("At least the tile_size option needs to be present")
|
||||
tile_step ||= tile_size
|
||||
|
||||
tp = RBA::TilingProcessor::new
|
||||
tp.dbu = @engine.dbu
|
||||
tp.scale_to_dbu = false
|
||||
tp.tile_size(*tile_step)
|
||||
if tile_size != tile_step
|
||||
xb = 0.5 * (tile_size[0] - tile_step[0])
|
||||
yb = 0.5 * (tile_size[1] - tile_step[1])
|
||||
tp.tile_border(xb, yb)
|
||||
tp.var("xoverlap", xb / tp.dbu)
|
||||
tp.var("yoverlap", yb / tp.dbu)
|
||||
else
|
||||
tp.var("xoverlap", 0)
|
||||
tp.var("yoverlap", 0)
|
||||
end
|
||||
if tile_origin
|
||||
tp.tile_origin(*tile_origin)
|
||||
end
|
||||
if tile_count
|
||||
tp.tiles(*tile_count)
|
||||
end
|
||||
|
||||
res = RBA::Region.new
|
||||
tp.output("res", res)
|
||||
tp.input("input", self.data)
|
||||
tp.threads = (@engine.threads || 1)
|
||||
if tile_boundary
|
||||
tp.input("boundary", tile_boundary.data)
|
||||
end
|
||||
|
||||
tp.var("vmin", limits[0] || 0.0)
|
||||
tp.var("vmax", limits[1] || 1.0)
|
||||
tp.var("inverse", inverse)
|
||||
tp.queue(<<"TP_SCRIPT")
|
||||
_tile && (
|
||||
var bx = _tile.bbox.enlarged(xoverlap, yoverlap);
|
||||
var d = to_f(input.area(bx)) / to_f(bx.area);
|
||||
((d > vmin - 1e-10 && d < vmax + 1e-10) != inverse) && _output(res, bx, false)
|
||||
)
|
||||
TP_SCRIPT
|
||||
|
||||
@engine.run_timed("\"#{method}\" in: #{@engine.src_line}", self.data) do
|
||||
tp.execute("Tiled \"#{method}\" in: #{@engine.src_line}")
|
||||
res
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, res)
|
||||
|
||||
end
|
||||
|
||||
def with_density(*args)
|
||||
self._with_density("with_density", false, *args)
|
||||
end
|
||||
|
||||
def without_density(*args)
|
||||
self._with_density("without_density", true, *args)
|
||||
end
|
||||
|
||||
|
||||
# %DRC%
|
||||
# @name scaled
|
||||
|
|
@ -3915,6 +4253,10 @@ CODE
|
|||
@data = d
|
||||
end
|
||||
|
||||
def check_is_layer(other)
|
||||
other.is_a?(DRCLayer) || raise("Argument needs to be a DRC layer")
|
||||
end
|
||||
|
||||
def requires_region
|
||||
self.data.is_a?(RBA::Region) || raise("Requires a polygon layer")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -180,6 +180,56 @@ module DRC
|
|||
@value
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the tile_size option
|
||||
class DRCTileSize
|
||||
def initialize(*args)
|
||||
@xy = args
|
||||
end
|
||||
def get
|
||||
@xy
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the tile_step option
|
||||
class DRCTileStep
|
||||
def initialize(*args)
|
||||
@xy = args
|
||||
end
|
||||
def get
|
||||
@xy
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the tile_origin option
|
||||
class DRCTileOrigin
|
||||
def initialize(*args)
|
||||
@xy = args
|
||||
end
|
||||
def get
|
||||
@xy
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the tile_count option
|
||||
class DRCTileCount
|
||||
def initialize(*args)
|
||||
@xy = args
|
||||
end
|
||||
def get
|
||||
@xy
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the tile_boundary option
|
||||
class DRCTileBoundary
|
||||
def initialize(layer)
|
||||
@b = layer
|
||||
end
|
||||
def get
|
||||
@b
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -17,44 +17,52 @@
|
|||
<text>
|
||||
module DRC
|
||||
|
||||
def DRC.execute_drc(macro, generator, rdb_index = nil)
|
||||
class DRCExecutable < RBA::Executable
|
||||
|
||||
timer = RBA::Timer::new
|
||||
timer.start
|
||||
drc = DRCEngine::new
|
||||
drc._rdb_index = rdb_index
|
||||
drc._generator = generator
|
||||
def initialize(macro, generator, rdb_index = nil)
|
||||
|
||||
drc_progress = RBA::AbstractProgress::new("DRC: " + macro.path)
|
||||
@drc = DRCEngine::new
|
||||
@drc._rdb_index = rdb_index
|
||||
@drc._generator = generator
|
||||
|
||||
begin
|
||||
|
||||
# Set a debugger scope so that our errors end up with the debugger set to the DRC's line
|
||||
RBA::MacroExecutionContext::set_debugger_scope(macro.path)
|
||||
# No verbosity set in drc engine - we cannot use the engine's logger
|
||||
RBA::Logger::verbosity >= 10 && RBA::Logger::info("Running #{macro.path}")
|
||||
drc.instance_eval(macro.text, macro.path)
|
||||
# Remove the debugger scope
|
||||
RBA::MacroExecutionContext::remove_debugger_scope
|
||||
|
||||
rescue => ex
|
||||
|
||||
drc.error("In #{macro.path}: #{ex.to_s}")
|
||||
RBA::MacroExecutionContext::ignore_next_exception
|
||||
raise ex
|
||||
|
||||
ensure
|
||||
|
||||
# cleans up and creates layout and report views
|
||||
drc._finish
|
||||
|
||||
# unlocks the UI
|
||||
drc_progress._destroy
|
||||
@macro = macro
|
||||
|
||||
end
|
||||
|
||||
timer.stop
|
||||
drc.info("Total run time: #{'%.3f'%(timer.sys+timer.user)}s")
|
||||
def execute
|
||||
|
||||
@drc._start("DRC: " + @macro.path)
|
||||
|
||||
# Set a debugger scope so that our errors end up with the debugger set to the DRC's line
|
||||
RBA::MacroExecutionContext::set_debugger_scope(@macro.path)
|
||||
|
||||
begin
|
||||
|
||||
# No verbosity set in drc engine - we cannot use the engine's logger
|
||||
RBA::Logger::verbosity >= 10 && RBA::Logger::info("Running #{@macro.path}")
|
||||
@drc.instance_eval(@macro.text, @macro.path)
|
||||
|
||||
rescue => ex
|
||||
|
||||
@drc.error("In #{@macro.path}: #{ex.to_s}")
|
||||
RBA::MacroExecutionContext::ignore_next_exception
|
||||
raise ex
|
||||
|
||||
end
|
||||
|
||||
nil
|
||||
|
||||
end
|
||||
|
||||
def cleanup
|
||||
|
||||
# Remove the debugger scope
|
||||
RBA::MacroExecutionContext::remove_debugger_scope
|
||||
|
||||
# cleans up and creates layout and report views
|
||||
@drc._finish
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -79,11 +87,17 @@ module DRC
|
|||
# create a template for the macro editor:
|
||||
create_template(":/drc-templates/drc.lym")
|
||||
|
||||
# if available, create a menu branch
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
mw = RBA::Application::instance.main_window
|
||||
mw.menu.insert_menu("tools_menu.verification_group+", "drc", "DRC")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Implements the execute method
|
||||
def execute(macro)
|
||||
DRC::execute_drc(macro, @recipe.generator("script" => macro.path))
|
||||
def executable(macro)
|
||||
DRCExecutable::new(macro, @recipe.generator("script" => macro.path))
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -109,20 +123,20 @@ module DRC
|
|||
end
|
||||
|
||||
# Implements the execute method
|
||||
def execute(macro)
|
||||
DRC::execute_drc(macro, @recipe.generator("script" => macro.path))
|
||||
def executable(macro)
|
||||
DRCExecutable::new(macro, @recipe.generator("script" => macro.path))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# A recipe implementation allowing the LVS run to be redone
|
||||
# A recipe implementation allowing the DRC run to be redone
|
||||
class DRCRecipe < RBA::Recipe
|
||||
|
||||
def initialize
|
||||
super("drc", "DRC recipe")
|
||||
end
|
||||
|
||||
def execute(params)
|
||||
def executable(params)
|
||||
|
||||
script = params["script"]
|
||||
if ! script
|
||||
|
|
@ -132,7 +146,7 @@ module DRC
|
|||
macro = RBA::Macro::macro_by_path(script)
|
||||
macro || raise("Can't find DRC script #{script} - unable to re-run")
|
||||
|
||||
DRC::execute_drc(macro, self.generator("script" => script), params["rdb_index"])
|
||||
DRCExecutable::new(macro, self.generator("script" => script), params["rdb_index"])
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1163,3 +1163,8 @@ TEST(29d_holes)
|
|||
run_test (_this, "29", true);
|
||||
}
|
||||
|
||||
TEST(30_density)
|
||||
{
|
||||
run_test (_this, "30", false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -629,6 +629,72 @@ Class<tl::GlobPattern> decl_GlobPattern ("tl", "GlobPattern",
|
|||
"This class has been introduced in version 0.26."
|
||||
);
|
||||
|
||||
class Executable_Impl
|
||||
: public tl::Executable, public gsi::ObjectBase
|
||||
{
|
||||
public:
|
||||
Executable_Impl ()
|
||||
: tl::Executable ()
|
||||
{
|
||||
// makes the object owned by the C++ side (registrar). This way we don't need to keep a
|
||||
// singleton instance.
|
||||
keep ();
|
||||
}
|
||||
|
||||
virtual tl::Variant execute ()
|
||||
{
|
||||
if (execute_cb.can_issue ()) {
|
||||
return execute_cb.issue<tl::Executable, tl::Variant> (&tl::Executable::execute);
|
||||
} else {
|
||||
return tl::Variant ();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void cleanup ()
|
||||
{
|
||||
if (cleanup_cb.can_issue ()) {
|
||||
cleanup_cb.issue<tl::Executable> (&tl::Executable::cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
gsi::Callback execute_cb;
|
||||
gsi::Callback cleanup_cb;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace tl
|
||||
{
|
||||
template <> struct type_traits<gsi::Executable_Impl> : public type_traits<tl::Executable> { };
|
||||
}
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
Class<tl::Executable> decl_Executable ("tl", "ExecutableBase",
|
||||
gsi::Methods (),
|
||||
"@hide\n@alias Executable"
|
||||
);
|
||||
|
||||
Class<Executable_Impl> decl_Executable_Impl (decl_Executable, "tl", "Executable",
|
||||
gsi::callback ("execute", &Executable_Impl::execute, &Executable_Impl::execute_cb,
|
||||
"@brief Reimplement this method to provide the functionality of the executable.\n"
|
||||
"This method is supposed to execute the operation with the given parameters and return the desired output."
|
||||
) +
|
||||
gsi::callback ("cleanup", &Executable_Impl::cleanup, &Executable_Impl::cleanup_cb,
|
||||
"@brief Reimplement this method to provide post-mortem cleanup functionality.\n"
|
||||
"This method is always called after execute terminated."
|
||||
),
|
||||
"@brief A generic executable object\n"
|
||||
"This object is a delegate for implementing the actual function of some generic executable function. "
|
||||
"In addition to the plain execution, if offers a post-mortem cleanup callback which is always executed, even "
|
||||
"if execute's implementation is cancelled in the debugger.\n"
|
||||
"\n"
|
||||
"Parameters are kept as a generic key/value map.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.27."
|
||||
);
|
||||
|
||||
class Recipe_Impl
|
||||
: public tl::Recipe, public gsi::ObjectBase
|
||||
{
|
||||
|
|
@ -641,16 +707,16 @@ public:
|
|||
keep ();
|
||||
}
|
||||
|
||||
virtual tl::Variant execute (const std::map<std::string, tl::Variant> ¶ms) const
|
||||
virtual tl::Executable *executable (const std::map<std::string, tl::Variant> ¶ms) const
|
||||
{
|
||||
if (execute_cb.can_issue ()) {
|
||||
return execute_cb.issue<tl::Recipe, tl::Variant, const std::map<std::string, tl::Variant> &> (&tl::Recipe::execute, params);
|
||||
if (executable_cb.can_issue ()) {
|
||||
return executable_cb.issue<tl::Recipe, tl::Executable *, const std::map<std::string, tl::Variant> &> (&tl::Recipe::executable, params);
|
||||
} else {
|
||||
return tl::Variant ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
gsi::Callback execute_cb;
|
||||
gsi::Callback executable_cb;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -688,10 +754,13 @@ Class<Recipe_Impl> decl_Recipe_Impl ("tl", "Recipe",
|
|||
"@brief Delivers the generator string from the given parameters.\n"
|
||||
"The generator string can be used with \\make to re-run the recipe."
|
||||
) +
|
||||
gsi::callback ("execute", &Recipe_Impl::execute, &Recipe_Impl::execute_cb, gsi::arg ("params"),
|
||||
"@brief Reimplement this method to provide the functionality of the recipe.\n"
|
||||
"This method is supposed to re-run the recipe with the given parameters and deliver the "
|
||||
"the intended output object."
|
||||
gsi::callback ("executable", &Recipe_Impl::executable, &Recipe_Impl::executable_cb, gsi::arg ("params"),
|
||||
"@brief Reimplement this method to provide an executable object for the actual implementation.\n"
|
||||
"The reasoning behind this architecture is to supply a cleanup callback. This is useful when the "
|
||||
"actual function is executed as a script and the script terminates in the debugger. The cleanup callback "
|
||||
"allows implementing any kind of post-mortem action despite being cancelled in the debugger.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27 and replaces 'execute'."
|
||||
),
|
||||
"@brief A facility for providing reproducable recipes\n"
|
||||
"The idea of this facility is to provide a service by which an object\n"
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ The following global functions are relevant for the DRC expressions:
|
|||
<li><a href="/about/drc_ref_global.xml#space">space</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#squares">squares</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#width">width</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#with_holes">with_holes</a> </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
The following documentation will list the methods available for DRC expression objects.
|
||||
|
|
@ -921,6 +922,22 @@ out = in.drc(primary.squares) # equivalent
|
|||
This method acts on edge expressions and delivers a specific part of each edge.
|
||||
See <a href="/about/drc_ref_layer.xml#start_segments">layer#start_segments</a> for details about this functionality.
|
||||
</p>
|
||||
<a name="with_holes"/><h2>"with_holes" - Selects all input polygons with the specified number of holes</h2>
|
||||
<keyword name="with_holes"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>expression.with_holes (in condition)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This operation can be used as a plain function in which case it acts on primary
|
||||
shapes or can be used as method on another DRC expression.
|
||||
The following example selects all polygons with more than 2 holes:
|
||||
</p><p>
|
||||
<pre>
|
||||
out = in.drc(with_holes > 2)
|
||||
out = in.drc(primary.with_holes > 2) # equivalent
|
||||
</pre>
|
||||
</p>
|
||||
<a name="|"/><h2>"|" - Boolean OR between the results of two expressions</h2>
|
||||
<keyword name="|"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -738,7 +738,7 @@ This function will evaluate the conditions c1 to cn and return the
|
|||
current primary shape if all conditions renders an empty result.
|
||||
See <a href="#if_all">if_all</a> for an example how to use the if_... functions.
|
||||
</p>
|
||||
<a name="info"/><h2>"info" - Outputs as message to the logger window</h2>
|
||||
<a name="info"/><h2>"info" - Outputs as message to the logger or progress window</h2>
|
||||
<keyword name="info"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
|
|
@ -747,7 +747,7 @@ See <a href="#if_all">if_all</a> for an example how to use the if_... functions.
|
|||
</ul>
|
||||
<p>
|
||||
Prints the message to the log window in verbose mode.
|
||||
In non-verbose more, nothing is printed.
|
||||
In non-verbose more, nothing is printed but a statement is put into the progress window.
|
||||
<a href="#log">log</a> is a function that always prints a message.
|
||||
</p>
|
||||
<a name="input"/><h2>"input" - Fetches the shapes from the specified input from the default source</h2>
|
||||
|
|
@ -1775,6 +1775,15 @@ In verbose mode, more output is generated in the log file
|
|||
<p>
|
||||
In verbose mode, more output is generated in the log file
|
||||
</p>
|
||||
<a name="warn"/><h2>"warn" - Prints a warning</h2>
|
||||
<keyword name="warn"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>warn(message)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
Similar to <a href="#log">log</a>, but the message is printed formatted as a warning
|
||||
</p>
|
||||
<a name="width"/><h2>"width" - Performs a width check</h2>
|
||||
<keyword name="width"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -1847,6 +1856,17 @@ shape.
|
|||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<a name="with_holes"/><h2>"with_holes" - Selects all input polygons according to their number of holes in DRC expressions</h2>
|
||||
<keyword name="with_holes"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>with_holes (in condition)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
"with_holes" represents a polygon selector for
|
||||
<a href="/about/drc_ref_drc.xml">DRC</a> expressions selecting polygons of the primary by their number of holes
|
||||
(see <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> and <a href="/about/drc_ref_drc.xml#with_holes">DRC#with_holes</a> for more details).
|
||||
</p>
|
||||
<a name="write_spice"/><h2>"write_spice" - Defines SPICE output format (with options)</h2>
|
||||
<keyword name="write_spice"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -247,8 +247,8 @@ deliver objects that can be converted into polygons. Such objects are of class <
|
|||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.corners([ options ])</tt></li>
|
||||
<li><tt>layer.corners(angle, [ options ])</tt></li>
|
||||
<li><tt>layer.corners(amin .. amax, [ options ])</tt></li>
|
||||
<li><tt>layer.corners(angle [, options ])</tt></li>
|
||||
<li><tt>layer.corners(amin .. amax [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method produces markers on the corners of the polygons. An angle criterion can be given which
|
||||
|
|
@ -2659,6 +2659,87 @@ The following image shows the effect of the space check:
|
|||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<a name="split_covering"/><h2>"split_covering" - Returns the results of <a href="#covering">covering</a> and <a href="#not_covering">not_covering</a> at the same time</h2>
|
||||
<keyword name="split_covering"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>(a, b) = layer.split_covering(other [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method returns the polygons covering polygons from the other layer in
|
||||
one layer and all others in a second layer. This method is equivalent to calling
|
||||
<a href="#covering">covering</a> and <a href="#not_covering">not_covering</a>, but is faster than doing this in separate steps:
|
||||
</p><p>
|
||||
<pre>
|
||||
(covering, not_covering) = l1.split_covering(l2)
|
||||
</pre>
|
||||
</p><p>
|
||||
The options of this method are the same than <a href="#covering">covering</a>.
|
||||
</p>
|
||||
<a name="split_inside"/><h2>"split_inside" - Returns the results of <a href="#inside">inside</a> and <a href="#not_inside">not_inside</a> at the same time</h2>
|
||||
<keyword name="split_inside"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>(a, b) = layer.split_inside(other)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method returns the polygons inside of polygons from the other layer in
|
||||
one layer and all others in a second layer. This method is equivalent to calling
|
||||
<a href="#inside">inside</a> and <a href="#not_inside">not_inside</a>, but is faster than doing this in separate steps:
|
||||
</p><p>
|
||||
<pre>
|
||||
(inside, not_inside) = l1.split_inside(l2)
|
||||
</pre>
|
||||
</p>
|
||||
<a name="split_interacting"/><h2>"split_interacting" - Returns the results of <a href="#interacting">interacting</a> and <a href="#not_interacting">not_interacting</a> at the same time</h2>
|
||||
<keyword name="split_interacting"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>(a, b) = layer.split_interacting(other [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method returns the polygons interacting with objects from the other container in
|
||||
one layer and all others in a second layer. This method is equivalent to calling
|
||||
<a href="#interacting">interacting</a> and <a href="#not_interacting">not_interacting</a>, but is faster than doing this in separate steps:
|
||||
</p><p>
|
||||
<pre>
|
||||
(interacting, not_interacting) = l1.split_interacting(l2)
|
||||
</pre>
|
||||
</p><p>
|
||||
The options of this method are the same than <a href="#interacting">interacting</a>.
|
||||
</p>
|
||||
<a name="split_outside"/><h2>"split_outside" - Returns the results of <a href="#outside">outside</a> and <a href="#not_outside">not_outside</a> at the same time</h2>
|
||||
<keyword name="split_outside"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>(a, b) = layer.split_outside(other)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method returns the polygons outside of polygons from the other layer in
|
||||
one layer and all others in a second layer. This method is equivalent to calling
|
||||
<a href="#outside">outside</a> and <a href="#not_outside">not_outside</a>, but is faster than doing this in separate steps:
|
||||
</p><p>
|
||||
<pre>
|
||||
(outside, not_outside) = l1.split_outside(l2)
|
||||
</pre>
|
||||
</p>
|
||||
<a name="split_overlapping"/><h2>"split_overlapping" - Returns the results of <a href="#overlapping">overlapping</a> and <a href="#not_overlapping">not_overlapping</a> at the same time</h2>
|
||||
<keyword name="split_overlapping"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>(a, b) = layer.split_overlapping(other [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method returns the polygons overlapping polygons from the other layer in
|
||||
one layer and all others in a second layer. This method is equivalent to calling
|
||||
<a href="#overlapping">overlapping</a> and <a href="#not_overlapping">not_overlapping</a>, but is faster than doing this in separate steps:
|
||||
</p><p>
|
||||
<pre>
|
||||
(overlapping, not_overlapping) = l1.split_overlapping(l2)
|
||||
</pre>
|
||||
</p><p>
|
||||
The options of this method are the same than <a href="#overlapping">overlapping</a>.
|
||||
</p>
|
||||
<a name="squares"/><h2>"squares" - Selects all squares from the input</h2>
|
||||
<keyword name="squares"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3074,6 +3155,86 @@ bounding box.
|
|||
</p><p>
|
||||
This method is available for polygon layers only.
|
||||
</p>
|
||||
<a name="with_density"/><h2>"with_density" - Returns tiles whose density is within a given range</h2>
|
||||
<keyword name="with_density"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.with_density(min_value, max_value [, options ])</tt></li>
|
||||
<li><tt>layer.with_density(min_value .. max_value [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method runs a tiled analysis over the current layout. It reports the tiles whose density
|
||||
is between "min_value" and "max_value". "min_value" and "max_value" are given in
|
||||
relative units, i.e. within the range of 0 to 1.0 corresponding to a density of 0 to 100%.
|
||||
</p><p>
|
||||
"min_value" or "max_value" can be nil or omitted in the ".." range notation.
|
||||
In this case, they are taken as "0" and "100%".
|
||||
</p><p>
|
||||
The tile size must be specified with the "tile_size" option:
|
||||
</p><p>
|
||||
<pre>
|
||||
# reports areas where layer 1/0 density is below 10% on 20x20 um tiles
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
|
||||
</pre>
|
||||
</p><p>
|
||||
Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
|
||||
The first value is the horizontal tile dimension, the second value is the vertical tile
|
||||
dimension.
|
||||
</p><p>
|
||||
A tile overlap can be specified using "tile_step". If the tile step is less than the
|
||||
tile size, the tiles will overlap. The layout window given by "tile_size" is moved
|
||||
in increments of the tile step:
|
||||
</p><p>
|
||||
<pre>
|
||||
# reports areas where layer 1/0 density is below 10% on 30x30 um tiles
|
||||
# with a tile step of 20x20 um:
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
|
||||
</pre>
|
||||
</p><p>
|
||||
For "tile_step", anisotropic values can be given as well by using two values: the first for the
|
||||
horizontal and the second for the vertical tile step.
|
||||
</p><p>
|
||||
Another option is "tile_origin" which specifies the location of the first tile's position.
|
||||
This is the lower left tile's lower left corner. If no origin is given, the tiles are centered over the
|
||||
area investigated.
|
||||
</p><p>
|
||||
By default, the tiles will cover the bounding box of the input layer. A separate layer
|
||||
can be used in addition. This way, the layout's dimensions can be derived from some
|
||||
drawn boundary layer. To specify a separate, additional layer included in the bounding box, use the "tile_boundary" option:
|
||||
</p><p>
|
||||
<pre>
|
||||
# reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
|
||||
# layer 0/0:
|
||||
cell_frame = input(0, 0)
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
|
||||
</pre>
|
||||
</p><p>
|
||||
Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
|
||||
The computed area is at least the area of the input layer.
|
||||
</p><p>
|
||||
Computation of the area can be skipped by explicitly giving a tile count in horizontal and vertical
|
||||
direction. With the "tile_origin" option this allows full control over the area covered:
|
||||
</p><p>
|
||||
<pre>
|
||||
# reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
|
||||
# (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
|
||||
</pre>
|
||||
</p><p>
|
||||
The complementary version of "with_density" is <a href="#without_density">without_density</a>.
|
||||
</p>
|
||||
<a name="with_holes"/><h2>"with_holes" - Selects all polygons with the specified number of holes</h2>
|
||||
<keyword name="with_holes"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.with_holes(count)</tt></li>
|
||||
<li><tt>layer.with_holes(min_count, max_count)</tt></li>
|
||||
<li><tt>layer.with_holes(min_count .. max_count)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method is available for polygon layers. It will select all polygons from the input layer
|
||||
which have the specified number of holes.
|
||||
</p>
|
||||
<a name="with_length"/><h2>"with_length" - Selects edges by their length</h2>
|
||||
<keyword name="with_length"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3228,6 +3389,29 @@ bounding box.
|
|||
</p><p>
|
||||
This method is available for polygon layers only.
|
||||
</p>
|
||||
<a name="without_density"/><h2>"without_density" - Returns tiles whose density is not within a given range</h2>
|
||||
<keyword name="without_density"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.without_density(min_value, max_value [, options ])</tt></li>
|
||||
<li><tt>layer.without_density(min_value .. max_value [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
For details about the operations and the operation see <a href="#with_density">with_density</a>. This version will return the
|
||||
tiles where the density is not within the given range.
|
||||
</p>
|
||||
<a name="without_holes"/><h2>"without_holes" - Selects all polygons with the specified number of holes</h2>
|
||||
<keyword name="without_holes"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.without_holes(count)</tt></li>
|
||||
<li><tt>layer.without_holes(min_count, max_count)</tt></li>
|
||||
<li><tt>layer.without_holes(min_count .. max_count)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method is available for polygon layers. It will select all polygons from the input layer
|
||||
which do not have the specified number of holes.
|
||||
</p>
|
||||
<a name="without_length"/><h2>"without_length" - Selects edges by the their length</h2>
|
||||
<keyword name="without_length"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.8 KiB |