mirror of https://github.com/KLayout/klayout.git
Ported edge/edge DRC functions to hierarchical mode.
This commit is contained in:
parent
c40f147dc7
commit
311318c578
|
|
@ -557,51 +557,6 @@ AsIfFlatEdges::filtered (const EdgeFilterBase &filter) const
|
|||
return new_region.release ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
|
||||
*
|
||||
* If will perform a edge by edge check using the provided EdgeRelationFilter
|
||||
*/
|
||||
template <class Output>
|
||||
class edge2edge_check_for_edges
|
||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
edge2edge_check_for_edges (const EdgeRelationFilter &check, Output &output, bool requires_different_layers)
|
||||
: mp_check (&check), mp_output (&output)
|
||||
{
|
||||
m_requires_different_layers = requires_different_layers;
|
||||
}
|
||||
|
||||
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
||||
{
|
||||
// Overlap or inside checks require input from different layers
|
||||
if (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0) {
|
||||
|
||||
// ensure that the first check argument is of layer 1 and the second of
|
||||
// layer 2 (unless both are of the same layer)
|
||||
int l1 = int (p1 & size_t (1));
|
||||
int l2 = int (p2 & size_t (1));
|
||||
|
||||
db::EdgePair ep;
|
||||
if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) {
|
||||
mp_output->insert (ep);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const EdgeRelationFilter *mp_check;
|
||||
Output *mp_output;
|
||||
bool m_requires_different_layers;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,6 +105,46 @@ private:
|
|||
std::set<const db::Edge *> m_seen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
|
||||
*
|
||||
* If will perform a edge by edge check using the provided EdgeRelationFilter
|
||||
*/
|
||||
template <class Output>
|
||||
class edge2edge_check_for_edges
|
||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
edge2edge_check_for_edges (const EdgeRelationFilter &check, Output &output, bool requires_different_layers)
|
||||
: mp_check (&check), mp_output (&output)
|
||||
{
|
||||
m_requires_different_layers = requires_different_layers;
|
||||
}
|
||||
|
||||
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
||||
{
|
||||
// Overlap or inside checks require input from different layers
|
||||
if (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0) {
|
||||
|
||||
// ensure that the first check argument is of layer 1 and the second of
|
||||
// layer 2 (unless both are of the same layer)
|
||||
int l1 = int (p1 & size_t (1));
|
||||
int l2 = int (p2 & size_t (1));
|
||||
|
||||
db::EdgePair ep;
|
||||
if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) {
|
||||
mp_output->insert (ep);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const EdgeRelationFilter *mp_check;
|
||||
Output *mp_output;
|
||||
bool m_requires_different_layers;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class to turn joined edge sequences into polygons
|
||||
*
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "dbRegion.h"
|
||||
#include "dbDeepEdges.h"
|
||||
#include "dbDeepRegion.h"
|
||||
#include "dbDeepEdgePairs.h"
|
||||
#include "dbHierNetworkProcessor.h"
|
||||
#include "dbCellGraphUtils.h"
|
||||
#include "dbCellVariants.h"
|
||||
|
|
@ -1174,10 +1175,123 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
|
|||
return AsIfFlatEdges::in (other, invert);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class CheckLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::EdgePair>
|
||||
{
|
||||
public:
|
||||
CheckLocalOperation (const EdgeRelationFilter &check, bool has_other)
|
||||
: m_check (check), m_has_other (has_other)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::unordered_set<db::EdgePair> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
edge2edge_check_for_edges<std::unordered_set<db::EdgePair> > edge_check (m_check, result, m_has_other);
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
std::set<db::Edge> others;
|
||||
|
||||
if (m_has_other) {
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert (& subject, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
others.insert (interactions.subject_shape (i->first));
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scanner.process (edge_check, m_check.distance (), db::box_convert<db::Edge> ());
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// TODO: will the distance be sufficient? Or should we take somewhat more?
|
||||
return m_check.distance ();
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Generic DRC check"));
|
||||
}
|
||||
|
||||
private:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_has_other;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgePairs DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::run_check (rel, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
const db::DeepEdges *other_deep = 0;
|
||||
if (other) {
|
||||
other_deep = dynamic_cast<const db::DeepEdges *> (other->delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatEdges::run_check (rel, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
}
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
check.set_whole_edges (whole_edges);
|
||||
check.set_ignore_angle (ignore_angle);
|
||||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_edges.derived ()));
|
||||
|
||||
db::CheckLocalOperation op (check, other_deep != 0);
|
||||
|
||||
db::local_processor<db::Edge, db::Edge, db::EdgePair> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()),
|
||||
const_cast<db::Cell *> (&m_deep_layer.initial_cell ()),
|
||||
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&m_deep_layer.layout ()),
|
||||
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&m_deep_layer.initial_cell ()));
|
||||
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_edges.layer (), other_deep ? other_deep->deep_layer ().layer () : m_merged_edges.layer (), res->deep_layer ().layer ());
|
||||
|
||||
return db::EdgePairs (res.release ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,3 +386,51 @@ TEST(8_SelectInteracting)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au8.gds");
|
||||
}
|
||||
|
||||
TEST(9_DRCChecks)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/deep_region_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0));
|
||||
unsigned int l4 = ly.get_layer (db::LayerProperties (4, 0));
|
||||
|
||||
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
|
||||
db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss);
|
||||
db::Region r4 (db::RecursiveShapeIterator (ly, top_cell, l4), dss);
|
||||
|
||||
db::Edges e3 = r3.edges ();
|
||||
db::Edges e4 = r4.edges ();
|
||||
db::Edges e6 = r6.edges ();
|
||||
|
||||
{
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (4, 0)), r4);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (6, 0)), r6);
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e3.space_check (500, false, db::Projection, 90, 0));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e3.space_check (500, true, db::Projection, 90, 300));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e3.separation_check (e4, 200, false, db::Projection, 90, 0));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e6.enclosing_check (e4, 100, true, db::Projection, 90, 0));
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au9.gds");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue