WIP: debugging

This commit is contained in:
Matthias Koefferlein 2020-12-25 15:00:52 +01:00
parent 45a8f7aa20
commit 4974a81af6
8 changed files with 230 additions and 121 deletions

View File

@ -1039,81 +1039,50 @@ AsIfFlatRegion::scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db
return new_region.release ();
}
EdgePairsDelegate *
AsIfFlatRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
template <class TR>
static
void region_cop_impl (AsIfFlatRegion *region, db::Shapes *output_to, db::CompoundRegionOperationNode &node)
{
db::local_processor<db::Polygon, db::Polygon, db::EdgePair> proc;
proc.set_base_verbosity (base_verbosity ());
db::local_processor<db::Polygon, db::Polygon, TR> proc;
proc.set_base_verbosity (region->base_verbosity ());
bool needs_merged = node.wants_merged ();
db::RegionIterator polygons (needs_merged ? region->begin_merged () : region->begin ());
std::vector<generic_shape_iterator<db::Polygon> > others;
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
// @@@ in case of *i == null - what to do?
others.push_back (*i ? (*i)->begin () : begin ());
others.push_back (*i ? (*i)->begin () : (needs_merged ? region->begin_merged () : region->begin ()));
}
// @@@ really always "merged"?
db::RegionIterator polygons (begin_merged ());
std::auto_ptr<FlatEdgePairs> output (new FlatEdgePairs ());
std::vector<db::Shapes *> results;
results.push_back (&output->raw_edge_pairs ());
results.push_back (output_to);
compound_local_operation<db::Polygon, db::Polygon, db::EdgePair> op (&node);
compound_local_operation<db::Polygon, db::Polygon, TR> op (&node);
proc.run_flat (polygons, others, &op, results);
}
EdgePairsDelegate *
AsIfFlatRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
{
std::auto_ptr<FlatEdgePairs> output (new FlatEdgePairs ());
region_cop_impl<db::EdgePair> (this, &output->raw_edge_pairs (), node);
return output.release ();
}
RegionDelegate *
AsIfFlatRegion::cop_to_region (db::CompoundRegionOperationNode &node)
{
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
proc.set_base_verbosity (base_verbosity ());
std::vector<generic_shape_iterator<db::Polygon> > others;
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
// @@@ in case of *i == null - what to do?
others.push_back (*i ? (*i)->begin () : begin ());
}
// @@@ really always "merged"?
db::RegionIterator polygons (begin_merged ());
std::auto_ptr<FlatRegion> output (new FlatRegion ());
std::vector<db::Shapes *> results;
results.push_back (&output->raw_polygons ());
compound_local_operation<db::Polygon, db::Polygon, db::Polygon> op (&node);
proc.run_flat (polygons, others, &op, results);
region_cop_impl<db::Polygon> (this, &output->raw_polygons (), node);
return output.release ();
}
EdgesDelegate *
AsIfFlatRegion::cop_to_edges (db::CompoundRegionOperationNode &node)
{
db::local_processor<db::Polygon, db::Polygon, db::Edge> proc;
proc.set_base_verbosity (base_verbosity ());
std::vector<generic_shape_iterator<db::Polygon> > others;
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
// @@@ in case of *i == null - what to do?
others.push_back (*i ? (*i)->begin () : begin ());
}
// @@@ really always "merged"?
db::RegionIterator polygons (begin_merged ());
std::auto_ptr<FlatEdges> output (new FlatEdges ());
std::vector<db::Shapes *> results;
results.push_back (&output->raw_edges ());
compound_local_operation<db::Polygon, db::Polygon, db::Edge> op (&node);
proc.run_flat (polygons, others, &op, results);
region_cop_impl<db::Edge> (this, &output->raw_edges (), node);
return output.release ();
}

View File

@ -163,7 +163,9 @@ CompoundRegionOperationPrimaryNode::~CompoundRegionOperationPrimaryNode ()
std::vector<db::Region *> CompoundRegionOperationPrimaryNode::inputs () const
{
return std::vector<db::Region *> ();
std::vector<db::Region *> is;
is.push_back (0);
return is;
}
void CompoundRegionOperationPrimaryNode::do_compute_local (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t, double) const
@ -299,13 +301,16 @@ CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode ()
CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *child)
{
child->keep ();
m_children.push_back (child);
init ();
}
CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b)
{
a->keep ();
m_children.push_back (a);
b->keep ();
m_children.push_back (b);
init ();
}
@ -415,6 +420,17 @@ CompoundRegionMultiInputOperationNode::wants_variants () const
return false;
}
bool
CompoundRegionMultiInputOperationNode::wants_merged () const
{
for (tl::shared_collection<CompoundRegionOperationNode>::const_iterator i = m_children.begin (); i != m_children.end (); ++i) {
if (i->wants_merged ()) {
return true;
}
}
return false;
}
// ---------------------------------------------------------------------------------------------
CompoundRegionLogicalBoolOperationNode::CompoundRegionLogicalBoolOperationNode (LogicalOp op, bool invert, const std::vector<CompoundRegionOperationNode *> &inputs)
@ -1113,18 +1129,58 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (db::edge_rel
m_check.set_max_projection (options.max_projection);
}
db::OnEmptyIntruderHint
CompoundRegionCheckOperationNode::on_empty_intruder_hint () const
{
return (m_different_polygons || !inputs ().empty ()) ? OnEmptyIntruderHint::Drop : OnEmptyIntruderHint::Ignore;
}
db::Coord
CompoundRegionCheckOperationNode::dist () const
{
return m_check.distance ();
}
bool
CompoundRegionCheckOperationNode::wants_merged () const
{
return true;
}
void
CompoundRegionCheckOperationNode::do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t max_vertex_count, double area_ratio) const
{
db::check_local_operation<db::Polygon, db::Polygon> op (m_check, m_different_polygons, true, false, m_options.shielded, m_options.opposite_filter, m_options.rect_filter);
op.compute_local (layout, interactions, results, max_vertex_count, area_ratio);
bool other_merged = (children () > 0 && !inputs ()[0]);
db::check_local_operation<db::Polygon, db::Polygon> op (m_check, m_different_polygons, children () > 0, other_merged, m_options.shielded, m_options.opposite_filter, m_options.rect_filter);
tl_assert (results.size () == 1);
if (results.front ().empty ()) {
op.compute_local (layout, interactions, results, max_vertex_count, area_ratio);
} else {
std::vector<std::unordered_set<db::EdgePair> > r;
r.resize (1);
op.compute_local (layout, interactions, r, max_vertex_count, area_ratio);
results.front ().insert (r.front ().begin (), r.front ().end ());
}
}
void
CompoundRegionCheckOperationNode::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
{
db::check_local_operation<db::PolygonRef, db::PolygonRef> op (m_check, m_different_polygons, true, false, m_options.shielded, m_options.opposite_filter, m_options.rect_filter);
op.compute_local (layout, interactions, results, max_vertex_count, area_ratio);
bool other_merged = (children () > 0 && !inputs ()[0]);
db::check_local_operation<db::PolygonRef, db::PolygonRef> op (m_check, m_different_polygons, children () > 0, other_merged, m_options.shielded, m_options.opposite_filter, m_options.rect_filter);
tl_assert (results.size () == 1);
if (results.front ().empty ()) {
op.compute_local (layout, interactions, results, max_vertex_count, area_ratio);
} else {
std::vector<std::unordered_set<db::EdgePair> > r;
r.resize (1);
op.compute_local (layout, interactions, r, max_vertex_count, area_ratio);
results.front ().insert (r.front ().begin (), r.front ().end ());
}
}
}

View File

@ -85,6 +85,11 @@ public:
*/
virtual bool wants_variants () const { return false; }
/**
* @brief Returns true, if the processor wants to have merged primary inputs
*/
virtual bool wants_merged () const { return false; }
void compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
{
implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio);
@ -362,6 +367,7 @@ public:
virtual const TransformationReducer *vars () const;
virtual bool wants_variants () const;
virtual bool wants_merged () const;
virtual void invalidate_cache () const;
@ -384,7 +390,12 @@ protected:
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
child_interactions.add_subject_shape (i->first, interactions.subject_shape (i->first));
if (child (child_index)->on_empty_intruder_hint () == OnEmptyIntruderHint::Drop) {
child_interactions.add_subject_shape (i->first, interactions.subject_shape (i->first));
} else {
// this includes the subject-without-intruder "interaction"
child_interactions.add_subject (i->first, interactions.subject_shape (i->first));
}
for (typename shape_interactions<TS, TI>::iterator2 ii = i->second.begin (); ii != i->second.end (); ++ii) {
@ -941,6 +952,10 @@ public:
// specifies the result type
virtual ResultType result_type () const { return EdgePairs; }
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual db::Coord dist () const;
virtual bool wants_merged () const;
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t max_vertex_count, double area_ratio) const;
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;
@ -981,8 +996,14 @@ protected:
shape_interactions<TS, TI> single_interactions;
single_interactions.add_subject_shape (i->first, subject_shape);
const std::vector<unsigned int> &intruders = single_interactions.intruders_for (i->first);
if (on_empty_intruder_hint () == OnEmptyIntruderHint::Drop) {
single_interactions.add_subject_shape (i->first, subject_shape);
} else {
// this includes the subject-without-intruder "interaction"
single_interactions.add_subject (i->first, subject_shape);
}
const std::vector<unsigned int> &intruders = interactions.intruders_for (i->first);
for (typename std::vector<unsigned int>::const_iterator ii = intruders.begin (); ii != intruders.end (); ++ii) {
const std::pair<unsigned int, TI> &is = interactions.intruder_shape (*ii);
single_interactions.add_intruder_shape (*ii, is.first, is.second);

View File

@ -1763,6 +1763,23 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
shape_interactions<TS, TI> interactions;
// insert dummy interactions to accommodate subject vs. nothing and assign an ID
// range for the subject shapes.
unsigned int subject_id0 = 0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
unsigned int id = interactions.next_id ();
if (subject_id0 == 0) {
subject_id0 = id;
}
if (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop) {
const TS *ref = i->basic_ptr (typename TS::tag ());
interactions.add_subject (id, *ref);
}
}
for (std::vector<unsigned int>::const_iterator il = contexts.intruder_layers ().begin (); il != contexts.intruder_layers ().end (); ++il) {
const db::Shapes *intruder_shapes = 0;
@ -1777,23 +1794,6 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
db::box_convert<db::CellInstArray, true> inst_bci (*mp_intruder_layout, *il);
// insert dummy interactions to accommodate subject vs. nothing and assign an ID
// range for the subject shapes.
unsigned int subject_id0 = 0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
unsigned int id = interactions.next_id ();
if (subject_id0 == 0) {
subject_id0 = id;
}
if (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop) {
const TS *ref = i->basic_ptr (typename TS::tag ());
interactions.add_subject (id, *ref);
}
}
typename std::map<unsigned int, std::set<TI> >::const_iterator ipl = intruders.second.find (*il);
static std::set<TI> empty_intruders;
@ -1900,7 +1900,7 @@ template <class TS, class TI>
struct scan_shape2shape_same_layer_flat
{
void
operator () (const generic_shape_iterator<TS> &, bool, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
operator () (const generic_shape_iterator<TS> &, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
{
// cannot have different types on the same layer
tl_assert (false);
@ -1911,7 +1911,7 @@ template <class T>
struct scan_shape2shape_same_layer_flat<T, T>
{
void
operator () (const generic_shape_iterator<T> &subjects, bool needs_isolated_subjects, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
operator () (const generic_shape_iterator<T> &subjects, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
{
db::box_scanner<T, int> scanner;
interaction_registration_shape1<T, T> rec (&interactions, intruder_layer);
@ -1924,22 +1924,32 @@ struct scan_shape2shape_same_layer_flat<T, T>
const T *shape = is.operator-> ();
scanner.insert (shape, id);
// create subject for subject vs. nothing interactions
if (needs_isolated_subjects) {
interactions.add_subject (id, *shape);
}
}
scanner.process (rec, dist, db::box_convert<T> ());
}
};
template <class TS, class TI>
struct add_subjects_vs_nothing_flat
{
void
operator () (const generic_shape_iterator<TS> &subjects, shape_interactions<TS, TI> &interactions) const
{
addressable_shape_delivery<TS> is (subjects);
for ( ; !is.at_end (); ++is) {
unsigned int id = interactions.next_id ();
const TS *shape = is.operator-> ();
interactions.add_subject (id, *shape);
}
}
};
template <class TS, class TI>
struct scan_shape2shape_different_layers_flat
{
void
operator () (const generic_shape_iterator<TS> &subjects, const generic_shape_iterator<TI> &intruders, bool needs_isolated_subjects, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
operator () (const generic_shape_iterator<TS> &subjects, const generic_shape_iterator<TI> &intruders, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
{
db::box_scanner2<TS, int, TI, int> scanner;
interaction_registration_shape2shape<TS, TI> rec (0 /*layout*/, &interactions, intruder_layer);
@ -1956,46 +1966,14 @@ struct scan_shape2shape_different_layers_flat
db::Box common_box = intruders_box & subjects_box;
if (common_box.empty ()) {
if (needs_isolated_subjects) {
for (generic_shape_iterator<TS> is = subjects; ! is.at_end (); ++is) {
// create subject for subject vs. nothing interactions
interactions.add_subject (interactions.next_id (), *is);
}
}
return;
}
addressable_shape_delivery<TS> is;
if (needs_isolated_subjects) {
box_convert<TS> bcs;
is = addressable_shape_delivery<TS> (subjects);
for ( ; !is.at_end (); ++is) {
unsigned int id = interactions.next_id ();
const TS *shape = is.operator-> ();
if (bcs (*shape).overlaps (common_box)) {
scanner.insert1 (shape, id);
}
// create subject for subject vs. nothing interactions
interactions.add_subject (id, *shape);
}
} else {
is = addressable_shape_delivery<TS> (subjects.confined (common_box, true));
for ( ; !is.at_end (); ++is) {
scanner.insert1 (is.operator-> (), interactions.next_id ());
}
is = addressable_shape_delivery<TS> (subjects.confined (common_box, true));
for ( ; !is.at_end (); ++is) {
scanner.insert1 (is.operator-> (), interactions.next_id ());
}
addressable_shape_delivery<TI> ii (intruders.confined (common_box, true));
@ -2022,13 +2000,16 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
tl_assert (mp_intruder_top == 0);
shape_interactions<TS, TI> interactions;
bool needs_isolated_subjects = (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop);
if (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop) {
add_subjects_vs_nothing_flat<TS, TI> () (subjects, interactions);
}
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
if (*il == subjects) {
scan_shape2shape_same_layer_flat<TS, TI> () (subjects, needs_isolated_subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
scan_shape2shape_same_layer_flat<TS, TI> () (subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
} else {
scan_shape2shape_different_layers_flat<TS, TI> () (subjects, *il, needs_isolated_subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
scan_shape2shape_different_layers_flat<TS, TI> () (subjects, *il, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
}
}

View File

@ -0,0 +1,81 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tlUnitTest.h"
#include "dbRegion.h"
#include "dbCompoundOperation.h"
#include "dbReader.h"
#include "dbRecursiveShapeIterator.h"
#include "dbTestSupport.h"
#include "tlStream.h"
#include <cstdio>
TEST(1_Basic)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/drc/compound_1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::RegionCheckOptions check_options;
check_options.metrics = db::Projection;
db::CompoundRegionCheckOperationNode width_check (db::WidthRelation, false /*==same polygon*/, 1050, check_options);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l1));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::Region r2 (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l2));
db::EdgePairs res = r.cop_to_edge_pairs (width_check);
unsigned int l1000 = ly.get_layer (db::LayerProperties (1000, 0));
res.insert_into (&ly, *ly.begin_top_down (), l1000);
db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode ();
db::CompoundRegionCheckOperationNode space_check (primary, db::SpaceRelation, true /*==different polygons*/, 1050, check_options);
res = r.cop_to_edge_pairs (space_check);
unsigned int l1001 = ly.get_layer (db::LayerProperties (1001, 0));
res.insert_into (&ly, *ly.begin_top_down (), l1001);
db::CompoundRegionOperationSecondaryNode *secondary = new db::CompoundRegionOperationSecondaryNode (&r2);
db::CompoundRegionCheckOperationNode sep_check (secondary, db::SpaceRelation, true /*==different polygons*/, 1050, check_options);
res = r.cop_to_edge_pairs (sep_check);
unsigned int l1002 = ly.get_layer (db::LayerProperties (1002, 0));
res.insert_into (&ly, *ly.begin_top_down (), l1002);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au1.gds");
}

View File

@ -7,6 +7,7 @@ TARGET = db_tests
include($$PWD/../../lib_ut.pri)
SOURCES = \
dbCompoundOperationTests.cc \
dbWriterTools.cc \
dbLoadLayoutOptionsTests.cc \
dbSaveLayoutOptionsTests.cc \

BIN
testdata/drc/compound_1.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/compound_au1.gds vendored Normal file

Binary file not shown.