Ported edge/edge DRC functions to hierarchical mode.

This commit is contained in:
Matthias Koefferlein 2019-02-17 18:54:33 +01:00
parent c40f147dc7
commit 311318c578
5 changed files with 204 additions and 47 deletions

View File

@ -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
{

View File

@ -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
*

View File

@ -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 ());
}
}

View File

@ -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");
}
}

BIN
testdata/algo/deep_edges_au9.gds vendored Normal file

Binary file not shown.