mirror of https://github.com/KLayout/klayout.git
Hierarchical implementation DRC functions (measurements)
This commit is contained in:
parent
5a994fef6d
commit
5dc833970b
|
|
@ -716,14 +716,14 @@ DeepRegion::to_string (size_t nmax) const
|
|||
EdgePairs
|
||||
DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
||||
{
|
||||
// NOTE: snap be optimized by forming grid variants etc.
|
||||
// TODO: snap be optimized by forming grid variants etc.
|
||||
return db::AsIfFlatRegion::grid_check (gx, gy);
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
DeepRegion::angle_check (double min, double max, bool inverse) const
|
||||
{
|
||||
// NOTE: snap be optimized by forming rotation variants etc.
|
||||
// TODO: snap be optimized by forming rotation variants etc.
|
||||
return db::AsIfFlatRegion::angle_check (min, max, inverse);
|
||||
}
|
||||
|
||||
|
|
@ -1241,41 +1241,63 @@ class CheckLocalOperation
|
|||
: public local_operation<db::PolygonRef, db::PolygonRef, db::EdgePair>
|
||||
{
|
||||
public:
|
||||
CheckLocalOperation (const EdgeRelationFilter &check, bool different_polygons)
|
||||
: m_check (check), m_different_polygons (different_polygons)
|
||||
CheckLocalOperation (const EdgeRelationFilter &check, bool different_polygons, bool has_other)
|
||||
: m_check (check), m_different_polygons (different_polygons), m_has_other (has_other)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
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, false, false);
|
||||
edge2edge_check<std::unordered_set<db::EdgePair> > edge_check (m_check, result, m_different_polygons, m_has_other);
|
||||
poly2poly_check<std::unordered_set<db::EdgePair> > poly_check (edge_check);
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
db::Polygon poly = subject.obj ().transformed (subject.trans ());
|
||||
poly_check.enter (poly, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
db::Polygon poly = o->obj ().transformed (o->trans ());
|
||||
poly_check.enter (poly, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
db::box_scanner<db::Polygon, size_t> scanner;
|
||||
|
||||
if (m_has_other) {
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
heap.push_back (subject.obj ().transformed (subject.trans ()));
|
||||
scanner.insert (& heap.back (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
heap.push_back (o->obj ().transformed (o->trans ()));
|
||||
scanner.insert (& heap.back (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
std::set<db::PolygonRef> polygons;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
polygons.insert (interactions.subject_shape (i->first));
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
polygons.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = polygons.begin (); o != polygons.end (); ++o) {
|
||||
heap.push_back (o->obj ().transformed (o->trans ()));
|
||||
scanner.insert (& heap.back (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
do {
|
||||
scanner.process (poly_check, m_check.distance (), db::box_convert<db::Polygon> ());
|
||||
} while (edge_check.prepare_next_pass ());
|
||||
|
|
@ -1283,7 +1305,7 @@ public:
|
|||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// TODO: will the distance be sufficient? Or should be take somewhat more?
|
||||
// TODO: will the distance be sufficient? Or should we take somewhat more?
|
||||
return m_check.distance ();
|
||||
}
|
||||
|
||||
|
|
@ -1300,6 +1322,7 @@ public:
|
|||
private:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_different_polygons;
|
||||
bool m_has_other;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1307,9 +1330,12 @@ private:
|
|||
EdgePairs
|
||||
DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other->delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
const db::DeepRegion *other_deep = 0;
|
||||
if (other) {
|
||||
other_deep = dynamic_cast<const db::DeepRegion *> (other->delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
|
|
@ -1320,16 +1346,19 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
|
||||
db::CheckLocalOperation op (check, different_polygons);
|
||||
db::CheckLocalOperation op (check, different_polygons, other_deep != 0);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, 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 ()));
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep ? other_deep->deep_layer ().layer () : m_merged_polygons.layer (), res->deep_layer ().layer ());
|
||||
|
||||
return db::EdgePairs (res.release ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,8 +274,18 @@ public:
|
|||
*
|
||||
* Creates an edge pair set representing a single instance of that object
|
||||
*/
|
||||
template <class Sh>
|
||||
explicit EdgePairs (const Sh &s)
|
||||
explicit EdgePairs (const db::EdgePair &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from an object
|
||||
*
|
||||
* Creates an edge pair set representing a single instance of that object
|
||||
*/
|
||||
explicit EdgePairs (const db::Shape &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
|
|
|
|||
|
|
@ -315,10 +315,10 @@ local_processor_cell_context<TS, TI, TR>::propagate (const std::unordered_set<TR
|
|||
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// LocalProcessorCellContexts implementation
|
||||
|
|
@ -1033,7 +1033,7 @@ template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef,
|
|||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// LocalProcessor implementation
|
||||
|
|
@ -1610,10 +1610,10 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
|
|||
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -927,6 +927,92 @@ TEST(16_MergeWithMinWC)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(17_SinglePolygonChecks)
|
||||
{
|
||||
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::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)), r3.width_check (260, false, db::Euclidian, 90, 0));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3.width_check (260, true, db::Projection, 90, 2000));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r6.notch_check (1300, false, db::Euclidian, 90, 0));
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au17.gds");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(18_Checks)
|
||||
{
|
||||
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::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)), r3.space_check (500, false, db::Projection, 90, 0));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3.space_check (500, true, db::Projection, 90, 300));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r3.separation_check (r4, 200, false, db::Projection, 90, 0));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r6.enclosing_check (r4, 100, true, db::Projection, 90, 0));
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au18.gds");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(100_Integration)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
|
|||
int layer = l->second.layer;
|
||||
int datatype = l->second.datatype;
|
||||
|
||||
db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Texts));
|
||||
db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::EdgePairs | db::ShapeIterator::Paths | db::ShapeIterator::Texts));
|
||||
while (! shape.at_end ()) {
|
||||
|
||||
progress_checkpoint ();
|
||||
|
|
@ -307,6 +307,9 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
|
|||
write_polygon (layer, datatype, sf, *shape, multi_xy, max_vertex_count, layout, shape->prop_id ());
|
||||
} else if (shape->is_edge ()) {
|
||||
write_edge (layer, datatype, sf, *shape, layout, shape->prop_id ());
|
||||
} else if (shape->is_edge_pair ()) {
|
||||
write_edge (layer, datatype, sf, shape->edge_pair ().first (), layout, shape->prop_id ());
|
||||
write_edge (layer, datatype, sf, shape->edge_pair ().second (), layout, shape->prop_id ());
|
||||
} else if (shape->is_path ()) {
|
||||
if (no_zero_length_paths && (shape->path_length () - shape->path_extensions ().first - shape->path_extensions ().second) == 0) {
|
||||
// eliminate the zero-width path
|
||||
|
|
@ -580,8 +583,12 @@ GDS2WriterBase::write_path (int layer, int datatype, double sf, const db::Shape
|
|||
void
|
||||
GDS2WriterBase::write_edge (int layer, int datatype, double sf, const db::Shape &shape, const db::Layout &layout, db::properties_id_type prop_id)
|
||||
{
|
||||
db::Edge e (shape.edge ());
|
||||
write_edge (layer, datatype, sf, shape.edge (), layout, prop_id);
|
||||
}
|
||||
|
||||
void
|
||||
GDS2WriterBase::write_edge (int layer, int datatype, double sf, const db::Edge &e, const db::Layout &layout, db::properties_id_type prop_id)
|
||||
{
|
||||
write_record_size (4);
|
||||
write_record (sPATH);
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,11 @@ protected:
|
|||
*/
|
||||
void write_edge (int layer, int datatype, double sf, const db::Shape &shape, const db::Layout &layout, db::properties_id_type prop_id);
|
||||
|
||||
/**
|
||||
* @brief Writes an edge
|
||||
*/
|
||||
void write_edge (int layer, int datatype, double sf, const db::Edge &edge, const db::Layout &layout, db::properties_id_type prop_id);
|
||||
|
||||
/**
|
||||
* @brief Write a shape as path
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue