mirror of https://github.com/KLayout/klayout.git
Merge branch 'issue-374' into drc-enhancements
This commit is contained in:
commit
689b3c5af9
|
|
@ -810,7 +810,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
|
||||||
check.set_min_projection (min_projection);
|
check.set_min_projection (min_projection);
|
||||||
check.set_max_projection (max_projection);
|
check.set_max_projection (max_projection);
|
||||||
|
|
||||||
edge2edge_check<db::FlatEdgePairs> edge_check (check, *result, different_polygons, other != 0);
|
edge2edge_check<db::FlatEdgePairs> edge_check (check, *result, different_polygons, other != 0 /*requires different layers*/, true /*shielded*/);
|
||||||
poly2poly_check<db::FlatEdgePairs> poly_check (edge_check);
|
poly2poly_check<db::FlatEdgePairs> poly_check (edge_check);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
@ -832,7 +832,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
|
||||||
check.set_min_projection (min_projection);
|
check.set_min_projection (min_projection);
|
||||||
check.set_max_projection (max_projection);
|
check.set_max_projection (max_projection);
|
||||||
|
|
||||||
edge2edge_check<db::FlatEdgePairs> edge_check (check, *result, false, false);
|
edge2edge_check<db::FlatEdgePairs> edge_check (check, *result, false /*=same polygons*/, false /*=same layers*/, true /*shielded*/);
|
||||||
poly2poly_check<db::FlatEdgePairs> poly_check (edge_check);
|
poly2poly_check<db::FlatEdgePairs> poly_check (edge_check);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
|
||||||
|
|
@ -1269,7 +1269,7 @@ public:
|
||||||
|
|
||||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::EdgePair> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::EdgePair> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||||
{
|
{
|
||||||
edge2edge_check<std::unordered_set<db::EdgePair> > edge_check (m_check, result, m_different_polygons, m_has_other);
|
edge2edge_check<std::unordered_set<db::EdgePair> > edge_check (m_check, result, m_different_polygons, m_has_other, true /*shielded*/);
|
||||||
poly2poly_check<std::unordered_set<db::EdgePair> > poly_check (edge_check);
|
poly2poly_check<std::unordered_set<db::EdgePair> > poly_check (edge_check);
|
||||||
|
|
||||||
std::list<db::Polygon> heap;
|
std::list<db::Polygon> heap;
|
||||||
|
|
@ -1408,7 +1408,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, b
|
||||||
|
|
||||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
|
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
|
||||||
|
|
||||||
edge2edge_check<db::Shapes> edge_check (check, result, false, false);
|
edge2edge_check<db::Shapes> edge_check (check, result, false, false, true /*shielded*/);
|
||||||
poly2poly_check<db::Shapes> poly_check (edge_check);
|
poly2poly_check<db::Shapes> poly_check (edge_check);
|
||||||
|
|
||||||
db::Polygon poly;
|
db::Polygon poly;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "dbRegionUtils.h"
|
#include "dbRegionUtils.h"
|
||||||
|
#include "dbEdgeBoolean.h"
|
||||||
#include "tlSelect.h"
|
#include "tlSelect.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
|
|
@ -30,9 +31,9 @@ namespace db
|
||||||
// -------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------
|
||||||
// Edge2EdgeCheckBase implementation
|
// Edge2EdgeCheckBase implementation
|
||||||
|
|
||||||
Edge2EdgeCheckBase::Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers)
|
Edge2EdgeCheckBase::Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||||
: mp_check (&check), m_requires_different_layers (requires_different_layers), m_different_polygons (different_polygons),
|
: mp_check (&check), m_requires_different_layers (requires_different_layers), m_different_polygons (different_polygons),
|
||||||
m_pass (0)
|
m_with_shielding (with_shielding), m_has_edge_pair_output (true), m_has_negative_edge_output (false), m_pass (0)
|
||||||
{
|
{
|
||||||
m_distance = check.distance ();
|
m_distance = check.distance ();
|
||||||
}
|
}
|
||||||
|
|
@ -44,22 +45,29 @@ Edge2EdgeCheckBase::prepare_next_pass ()
|
||||||
|
|
||||||
if (m_pass == 1) {
|
if (m_pass == 1) {
|
||||||
|
|
||||||
if (! m_ep.empty ()) {
|
if (m_with_shielding && ! m_ep.empty ()) {
|
||||||
m_ep_discarded.resize (m_ep.size (), false);
|
m_ep_discarded.resize (m_ep.size (), false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (m_pass == 2) {
|
} else if (m_pass == 2) {
|
||||||
|
|
||||||
std::vector<bool>::const_iterator d = m_ep_discarded.begin ();
|
if (m_has_edge_pair_output) {
|
||||||
std::vector<db::EdgePair>::const_iterator ep = m_ep.begin ();
|
|
||||||
while (ep != m_ep.end ()) {
|
std::vector<bool>::const_iterator d = m_ep_discarded.begin ();
|
||||||
tl_assert (d != m_ep_discarded.end ());
|
std::vector<db::EdgePair>::const_iterator ep = m_ep.begin ();
|
||||||
if (! *d) {
|
while (ep != m_ep.end ()) {
|
||||||
put (*ep);
|
bool use_result = true;
|
||||||
|
if (d != m_ep_discarded.end ()) {
|
||||||
|
use_result = ! *d;
|
||||||
|
++d;
|
||||||
|
}
|
||||||
|
if (use_result) {
|
||||||
|
put (*ep);
|
||||||
|
}
|
||||||
|
++ep;
|
||||||
}
|
}
|
||||||
++d;
|
|
||||||
++ep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +90,18 @@ static inline bool shields (const db::EdgePair &ep, const db::Edge &q)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Edge2EdgeCheckBase::finish (const Edge *o, const size_t &p)
|
||||||
|
{
|
||||||
|
if (m_has_negative_edge_output && m_pass == 1) {
|
||||||
|
|
||||||
|
// no interaction at all: create a single-edged edge pair
|
||||||
|
int l = int (p & size_t (1));
|
||||||
|
put_negative (*o, l);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
||||||
{
|
{
|
||||||
|
|
@ -99,7 +119,8 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
|
||||||
if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) {
|
if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) {
|
||||||
|
|
||||||
// found a violation: store inside the local buffer for now. In the second
|
// found a violation: store inside the local buffer for now. In the second
|
||||||
// pass we will eliminate those which are shielded completely.
|
// pass we will eliminate those which are shielded completely (with shielding)
|
||||||
|
// and/or compute the negative edges.
|
||||||
size_t n = m_ep.size ();
|
size_t n = m_ep.size ();
|
||||||
m_ep.push_back (ep);
|
m_ep.push_back (ep);
|
||||||
m_e2ep.insert (std::make_pair (std::make_pair (*o1, p1), n));
|
m_e2ep.insert (std::make_pair (std::make_pair (*o1, p1), n));
|
||||||
|
|
@ -111,48 +132,97 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// a simple (complete) shielding implementation which is based on the
|
// set the discarded flags for shielded output
|
||||||
// assumption that shielding is relevant as soon as a foreign edge cuts through
|
if (m_with_shielding) {
|
||||||
// both of the edge pair's connecting edges.
|
|
||||||
|
|
||||||
// TODO: this implementation does not take into account the nature of the
|
// a simple (complete) shielding implementation which is based on the
|
||||||
// EdgePair - because of "whole_edge" it may not reflect the part actually
|
// assumption that shielding is relevant as soon as a foreign edge cuts through
|
||||||
// violating the distance.
|
// both of the edge pair's connecting edges.
|
||||||
|
|
||||||
std::vector<size_t> n1, n2;
|
// TODO: this implementation does not take into account the nature of the
|
||||||
|
// EdgePair - because of "whole_edge" it may not reflect the part actually
|
||||||
|
// violating the distance.
|
||||||
|
|
||||||
for (unsigned int p = 0; p < 2; ++p) {
|
std::vector<size_t> n1, n2;
|
||||||
|
|
||||||
|
for (unsigned int p = 0; p < 2; ++p) {
|
||||||
|
|
||||||
|
std::pair<db::Edge, size_t> k (*o1, p1);
|
||||||
|
for (std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i = m_e2ep.find (k); i != m_e2ep.end () && i->first == k; ++i) {
|
||||||
|
n1.push_back (i->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort (n1.begin (), n1.end ());
|
||||||
|
|
||||||
|
std::swap (o1, o2);
|
||||||
|
std::swap (p1, p2);
|
||||||
|
n1.swap (n2);
|
||||||
|
|
||||||
std::pair<db::Edge, size_t> k (*o1, p1);
|
|
||||||
for (std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i = m_e2ep.find (k); i != m_e2ep.end () && i->first == k; ++i) {
|
|
||||||
n1.push_back (i->second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort (n1.begin (), n1.end ());
|
for (unsigned int p = 0; p < 2; ++p) {
|
||||||
|
|
||||||
std::swap (o1, o2);
|
std::vector<size_t> nn;
|
||||||
std::swap (p1, p2);
|
std::set_difference (n1.begin (), n1.end (), n2.begin (), n2.end (), std::back_inserter (nn));
|
||||||
n1.swap (n2);
|
|
||||||
|
for (std::vector<size_t>::const_iterator i = nn.begin (); i != nn.end (); ++i) {
|
||||||
|
if (! m_ep_discarded [*i]) {
|
||||||
|
db::EdgePair ep = m_ep [*i].normalized ();
|
||||||
|
if (shields (ep, *o2)) {
|
||||||
|
m_ep_discarded [*i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::swap (o1, o2);
|
||||||
|
std::swap (p1, p2);
|
||||||
|
n1.swap (n2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int p = 0; p < 2; ++p) {
|
// prepare the negative edge output
|
||||||
|
if (m_has_negative_edge_output) {
|
||||||
|
|
||||||
std::vector<size_t> nn;
|
// Overlap or inside checks require input from different layers
|
||||||
std::set_difference (n1.begin (), n1.end (), n2.begin (), n2.end (), std::back_inserter (nn));
|
if ((! m_different_polygons || p1 != p2) && (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0)) {
|
||||||
|
|
||||||
for (std::vector<size_t>::const_iterator i = nn.begin (); i != nn.end (); ++i) {
|
for (int p = 0; p < 2; ++p) {
|
||||||
if (! m_ep_discarded [*i]) {
|
|
||||||
db::EdgePair ep = m_ep [*i].normalized ();
|
std::pair<db::Edge, size_t> k (*o1, p1);
|
||||||
if (shields (ep, *o2)) {
|
std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i0 = m_e2ep.find (k);
|
||||||
m_ep_discarded [*i] = true;
|
|
||||||
|
bool fully_removed = false;
|
||||||
|
for (std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i = i0; ! fully_removed && i != m_e2ep.end () && i->first == k; ++i) {
|
||||||
|
fully_removed = (m_ep [i->second].first () == *o1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::swap (o1, o2);
|
if (! fully_removed) {
|
||||||
std::swap (p1, p2);
|
|
||||||
n1.swap (n2);
|
std::set<db::Edge> partial_edges;
|
||||||
|
|
||||||
|
db::EdgeBooleanCluster<std::set<db::Edge> > ec (&partial_edges, db::EdgeNot);
|
||||||
|
ec.add (o1, 0);
|
||||||
|
|
||||||
|
for (std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i = i0; i != m_e2ep.end () && i->first == k; ++i) {
|
||||||
|
ec.add (&m_ep [i->second].first (), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ec.finish ();
|
||||||
|
|
||||||
|
for (std::set<db::Edge>::const_iterator e = partial_edges.begin (); e != partial_edges.end (); ++e) {
|
||||||
|
put_negative (*e, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::swap (o1, o2);
|
||||||
|
std::swap (p1, p2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ class DB_PUBLIC Edge2EdgeCheckBase
|
||||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers);
|
Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers, bool with_shielding);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Call this to initiate a new pass until the return value is false
|
* @brief Call this to initiate a new pass until the return value is false
|
||||||
|
|
@ -380,6 +380,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2);
|
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the box_scanner_receiver interface
|
||||||
|
*/
|
||||||
|
void finish (const Edge *o, const size_t &);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a value indicating whether the check requires different layers
|
* @brief Gets a value indicating whether the check requires different layers
|
||||||
*/
|
*/
|
||||||
|
|
@ -400,13 +405,37 @@ public:
|
||||||
*/
|
*/
|
||||||
void set_different_polygons (bool f);
|
void set_different_polygons (bool f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a flag indicating that this class wants negative edge output
|
||||||
|
*/
|
||||||
|
void set_has_negative_edge_output (bool f)
|
||||||
|
{
|
||||||
|
m_has_negative_edge_output = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a flag indicating that this class wants normal edge pair output
|
||||||
|
*/
|
||||||
|
void set_has_edge_pair_output (bool f)
|
||||||
|
{
|
||||||
|
m_has_edge_pair_output = f;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the distance value
|
* @brief Gets the distance value
|
||||||
*/
|
*/
|
||||||
EdgeRelationFilter::distance_type distance () const;
|
EdgeRelationFilter::distance_type distance () const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void put (const db::EdgePair &edge) const = 0;
|
/**
|
||||||
|
* @brief Normal edge pair output (violations)
|
||||||
|
*/
|
||||||
|
virtual void put (const db::EdgePair & /*edge*/) const { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Negative edge output
|
||||||
|
*/
|
||||||
|
virtual void put_negative (const db::Edge & /*edge*/, int /*layer*/) const { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EdgeRelationFilter *mp_check;
|
const EdgeRelationFilter *mp_check;
|
||||||
|
|
@ -416,19 +445,24 @@ private:
|
||||||
std::vector<db::EdgePair> m_ep;
|
std::vector<db::EdgePair> m_ep;
|
||||||
std::multimap<std::pair<db::Edge, size_t>, size_t> m_e2ep;
|
std::multimap<std::pair<db::Edge, size_t>, size_t> m_e2ep;
|
||||||
std::vector<bool> m_ep_discarded;
|
std::vector<bool> m_ep_discarded;
|
||||||
|
bool m_with_shielding;
|
||||||
|
bool m_has_edge_pair_output;
|
||||||
|
bool m_has_negative_edge_output;
|
||||||
unsigned int m_pass;
|
unsigned int m_pass;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
|
* @brief A helper class for the DRC functionality
|
||||||
|
*
|
||||||
|
* This class implements the edge-to-edge part of the polygon DRC.
|
||||||
*/
|
*/
|
||||||
template <class Output>
|
template <class Output>
|
||||||
class DB_PUBLIC_TEMPLATE edge2edge_check
|
class DB_PUBLIC_TEMPLATE edge2edge_check
|
||||||
: public Edge2EdgeCheckBase
|
: public Edge2EdgeCheckBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers)
|
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers), mp_output (&output)
|
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding), mp_output (&output)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -443,6 +477,82 @@ private:
|
||||||
Output *mp_output;
|
Output *mp_output;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A helper class for the DRC functionality
|
||||||
|
*
|
||||||
|
* This class implements the edge-to-edge part of the polygon DRC.
|
||||||
|
* This version allows delivery of the negative edges.
|
||||||
|
*/
|
||||||
|
template <class Output, class NegativeEdgeOutput>
|
||||||
|
class DB_PUBLIC_TEMPLATE edge2edge_check_with_negative_output
|
||||||
|
: public Edge2EdgeCheckBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||||
|
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding),
|
||||||
|
mp_output (&output),
|
||||||
|
mp_l1_negative_output (&l1_negative_output),
|
||||||
|
mp_l2_negative_output (&l2_negative_output)
|
||||||
|
{
|
||||||
|
set_has_negative_edge_output (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void put (const db::EdgePair &ep) const
|
||||||
|
{
|
||||||
|
mp_output->insert (ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void put_negative (const db::Edge &edge, int layer) const
|
||||||
|
{
|
||||||
|
if (layer == 0) {
|
||||||
|
mp_l1_negative_output->insert (edge);
|
||||||
|
}
|
||||||
|
if (layer == 1) {
|
||||||
|
mp_l2_negative_output->insert (edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Output *mp_output;
|
||||||
|
NegativeEdgeOutput *mp_l1_negative_output, *mp_l2_negative_output;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A helper class for the DRC functionality
|
||||||
|
*
|
||||||
|
* This class implements the edge-to-edge part of the polygon DRC.
|
||||||
|
* This version has only negative edge output.
|
||||||
|
*/
|
||||||
|
template <class Output, class NegativeEdgeOutput>
|
||||||
|
class DB_PUBLIC_TEMPLATE edge2edge_check_negative
|
||||||
|
: public Edge2EdgeCheckBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
edge2edge_check_negative (const EdgeRelationFilter &check, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||||
|
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding),
|
||||||
|
mp_l1_negative_output (&l1_negative_output),
|
||||||
|
mp_l2_negative_output (&l2_negative_output)
|
||||||
|
{
|
||||||
|
set_has_negative_edge_output (true);
|
||||||
|
set_has_edge_pair_output (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void put_negative (const db::Edge &edge, int layer) const
|
||||||
|
{
|
||||||
|
if (layer == 0) {
|
||||||
|
mp_l1_negative_output->insert (edge);
|
||||||
|
}
|
||||||
|
if (layer == 1) {
|
||||||
|
mp_l2_negative_output->insert (edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NegativeEdgeOutput *mp_l1_negative_output, *mp_l2_negative_output;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
|
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue