WIP: Bugfixed deep processor (multi-input mode and input layer index), added tests

This commit is contained in:
Matthias Koefferlein 2020-12-26 19:43:51 +01:00
parent dc80ed77b1
commit afc9fc9c7a
7 changed files with 133 additions and 128 deletions

View File

@ -418,7 +418,7 @@ std::string CompoundRegionLogicalBoolOperationNode::generated_description () con
} else if (m_op == Or) {
r += "or";
}
return r + CompoundRegionMultiInputOperationNode::description ();
return r + CompoundRegionMultiInputOperationNode::generated_description ();
}
template <class T>
@ -482,7 +482,7 @@ CompoundRegionGeometricalBoolOperationNode::generated_description () const
} else if (m_op == Not) {
r = "not";
}
r += CompoundRegionMultiInputOperationNode::description ();
r += CompoundRegionMultiInputOperationNode::generated_description ();
return r;
}
@ -499,6 +499,21 @@ CompoundRegionGeometricalBoolOperationNode::result_type () const
}
}
db::Coord
CompoundRegionGeometricalBoolOperationNode::dist () const
{
db::Coord d = CompoundRegionMultiInputOperationNode::dist ();
ResultType res_a = child (0)->result_type ();
ResultType res_b = child (1)->result_type ();
if (res_a == Region && res_b == Region) {
return d; // overlapping is sufficient
} else {
return d + 1; // we need "touching" if edges are involved
}
}
template <class T1, class T2, class TR>
static
void run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp, db::Layout *, const std::unordered_set<T1> &, const std::unordered_set<T2> &, const std::unordered_set<TR> &)
@ -868,7 +883,7 @@ std::string CompoundRegionLogicalCaseSelectOperationNode::generated_description
// TODO: could be nicer ...
std::string r;
r = "if-then";
return r + CompoundRegionMultiInputOperationNode::description ();
return r + CompoundRegionMultiInputOperationNode::generated_description ();
}
CompoundRegionLogicalCaseSelectOperationNode::ResultType

View File

@ -61,6 +61,11 @@ public:
CompoundRegionOperationNode ();
virtual ~CompoundRegionOperationNode ();
const std::string &raw_description () const
{
return m_description;
}
std::string description () const;
void set_description (const std::string &d);
@ -425,6 +430,7 @@ public:
// specifies the result type
virtual ResultType result_type () const;
virtual db::Coord dist () const;
// the different computation slots
virtual void do_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;

View File

@ -1343,22 +1343,37 @@ DeepRegion::in (const Region &other, bool invert) const
return db::AsIfFlatRegion::in (other, invert);
}
EdgePairsDelegate *
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
template <class TR, class Output>
static
Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &node)
{
std::vector<unsigned int> other_layers;
// Fall back to flat mode if one of the inputs is flat
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
if (*i && ! dynamic_cast<const db::DeepRegion *> ((*i)->delegate ())) {
return 0;
}
}
db::local_processor<db::PolygonRef, db::PolygonRef, TR> proc (const_cast<db::Layout *> (&region->deep_layer ().layout ()),
const_cast<db::Cell *> (&region->deep_layer ().initial_cell ()),
region->deep_layer ().breakout_cells ());
proc.set_base_verbosity (region->base_verbosity ());
proc.set_threads (region->deep_layer ().store ()->threads ());
bool needs_merged = node.wants_merged ();
const db::DeepLayer &polygons (needs_merged ? region->merged_deep_layer () : region->deep_layer ());
std::vector<unsigned int> other_layers;
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
if (! *i) {
// @@@ in case of *i == null - what to do?
other_layers.push_back (deep_layer ().layer ());
other_layers.push_back (polygons.layer ());
} else {
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> ((*i)->delegate ());
if (! other_deep) {
return db::AsIfFlatRegion::cop_to_edge_pairs (node);
}
if (&other_deep->deep_layer ().layout () != &deep_layer ().layout () || &other_deep->deep_layer ().initial_cell () != &deep_layer ().initial_cell ()) {
tl_assert (other_deep != 0);
if (&other_deep->deep_layer ().layout () != &region->deep_layer ().layout () || &other_deep->deep_layer ().initial_cell () != &region->deep_layer ().initial_cell ()) {
throw tl::Exception (tl::to_string (tr ("Complex DeepRegion operations need to use the same layout and top cell for all inputs")));
}
other_layers.push_back (other_deep->deep_layer ().layer ());
@ -1366,104 +1381,44 @@ DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
}
// @@@ really always "merged"?
const db::DeepLayer &polygons = merged_deep_layer ();
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&deep_layer ().layout ()),
const_cast<db::Cell *> (&deep_layer ().initial_cell ()),
deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
compound_local_operation<db::PolygonRef, db::PolygonRef, db::EdgePair> op (&node);
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
std::auto_ptr<Output> res (new Output (polygons.derived ()));
compound_local_operation<db::PolygonRef, db::PolygonRef, TR> op (&node);
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
return res.release ();
}
EdgePairsDelegate *
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
{
DeepEdgePairs *output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node);
if (! output) {
return AsIfFlatRegion::cop_to_edge_pairs (node);
} else {
return output;
}
}
RegionDelegate *
DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node)
{
std::vector<unsigned int> other_layers;
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
if (! *i) {
// @@@ in case of *i == null - what to do?
other_layers.push_back (deep_layer ().layer ());
} else {
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> ((*i)->delegate ());
if (! other_deep) {
return db::AsIfFlatRegion::cop_to_region (node);
}
if (&other_deep->deep_layer ().layout () != &deep_layer ().layout () || &other_deep->deep_layer ().initial_cell () != &deep_layer ().initial_cell ()) {
throw tl::Exception (tl::to_string (tr ("Complex DeepRegion operations need to use the same layout and top cell for all inputs")));
}
other_layers.push_back (other_deep->deep_layer ().layer ());
}
DeepRegion *output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node);
if (! output) {
return AsIfFlatRegion::cop_to_region (node);
} else {
return output;
}
// @@@ really always "merged"?
const db::DeepLayer &polygons = merged_deep_layer ();
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()),
const_cast<db::Cell *> (&deep_layer ().initial_cell ()),
deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
compound_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> op (&node);
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (polygons.derived ()));
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
return res.release ();
}
EdgesDelegate *
DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node)
{
std::vector<unsigned int> other_layers;
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
if (! *i) {
// @@@ in case of *i == null - what to do?
other_layers.push_back (deep_layer ().layer ());
} else {
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> ((*i)->delegate ());
if (! other_deep) {
return db::AsIfFlatRegion::cop_to_edges (node);
}
if (&other_deep->deep_layer ().layout () != &deep_layer ().layout () || &other_deep->deep_layer ().initial_cell () != &deep_layer ().initial_cell ()) {
throw tl::Exception (tl::to_string (tr ("Complex DeepRegion operations need to use the same layout and top cell for all inputs")));
}
other_layers.push_back (other_deep->deep_layer ().layer ());
}
DeepEdges *output = region_cop_impl<db::Edge, db::DeepEdges> (this, node);
if (! output) {
return AsIfFlatRegion::cop_to_edges (node);
} else {
return output;
}
// @@@ really always "merged"?
const db::DeepLayer &polygons = merged_deep_layer ();
db::local_processor<db::PolygonRef, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&deep_layer ().layout ()),
const_cast<db::Cell *> (&deep_layer ().initial_cell ()),
deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
compound_local_operation<db::PolygonRef, db::PolygonRef, db::Edge> op (&node);
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (polygons.derived ()));
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
return res.release ();
}
EdgePairsDelegate *

View File

@ -132,6 +132,8 @@ public:
void set_is_merged (bool f);
const DeepLayer &merged_deep_layer () const;
protected:
virtual void merged_semantics_changed ();
virtual void min_coherence_changed ();
@ -157,7 +159,6 @@ private:
void init ();
void ensure_merged_polygons_valid () const;
const DeepLayer &merged_deep_layer () const;
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other) const;
DeepRegion *apply_filter (const PolygonFilterBase &filter) const;

View File

@ -718,8 +718,8 @@ struct interaction_registration_shape2shape
: db::box_scanner_receiver2<TS, unsigned int, TI, unsigned int>
{
public:
interaction_registration_shape2shape (db::Layout *layout, shape_interactions<TS, TI> *result, unsigned int intruder_layer)
: mp_result (result), mp_layout (layout), m_intruder_layer (intruder_layer)
interaction_registration_shape2shape (db::Layout *layout, shape_interactions<TS, TI> *result, unsigned int intruder_layer_index)
: mp_result (result), mp_layout (layout), m_intruder_layer_index (intruder_layer_index)
{
// nothing yet ..
}
@ -735,9 +735,9 @@ public:
// In order to guarantee the refs come from the subject layout, we'd need to
// rewrite them
db::shape_reference_translator<TI> rt (mp_layout);
mp_result->add_intruder_shape (id2, m_intruder_layer, rt (*ref2));
mp_result->add_intruder_shape (id2, m_intruder_layer_index, rt (*ref2));
} else {
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
mp_result->add_intruder_shape (id2, m_intruder_layer_index, *ref2);
}
}
@ -747,7 +747,7 @@ public:
private:
shape_interactions<TS, TI> *mp_result;
db::Layout *mp_layout;
unsigned int m_intruder_layer;
unsigned int m_intruder_layer_index;
};
template <class TS, class TI>
@ -755,8 +755,8 @@ struct interaction_registration_shape1
: db::box_scanner_receiver2<TS, unsigned int, TI, unsigned int>
{
public:
interaction_registration_shape1 (shape_interactions<TS, TI> *result, unsigned int intruder_layer)
: mp_result (result), m_intruder_layer (intruder_layer)
interaction_registration_shape1 (shape_interactions<TS, TI> *result, unsigned int intruder_layer_index)
: mp_result (result), m_intruder_layer_index (intruder_layer_index)
{
// nothing yet ..
}
@ -767,14 +767,14 @@ public:
mp_result->add_subject_shape (id1, *ref1);
}
if (!mp_result->has_intruder_shape_id (id2)) {
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
mp_result->add_intruder_shape (id2, m_intruder_layer_index, *ref2);
}
mp_result->add_interaction (id1, id2);
}
private:
shape_interactions<TS, TI> *mp_result;
unsigned int m_intruder_layer;
unsigned int m_intruder_layer_index;
};
template <class T>
@ -782,8 +782,8 @@ struct interaction_registration_shape1<T, T>
: db::box_scanner_receiver<T, unsigned int>
{
public:
interaction_registration_shape1 (shape_interactions<T, T> *result, unsigned int intruder_layer)
: mp_result (result), m_intruder_layer (intruder_layer)
interaction_registration_shape1 (shape_interactions<T, T> *result, unsigned int intruder_layer_index)
: mp_result (result), m_intruder_layer_index (intruder_layer_index)
{
// nothing yet ..
}
@ -794,14 +794,14 @@ public:
mp_result->add_subject_shape (id1, *ref1);
}
if (!mp_result->has_intruder_shape_id (id2)) {
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
mp_result->add_intruder_shape (id2, m_intruder_layer_index, *ref2);
}
mp_result->add_interaction (id1, id2);
}
private:
shape_interactions<T, T> *mp_result;
unsigned int m_intruder_layer;
unsigned int m_intruder_layer_index;
};
template <class TS, class TI>
@ -809,8 +809,8 @@ struct interaction_registration_shape2inst
: db::box_scanner_receiver2<TS, unsigned int, db::CellInstArray, unsigned int>
{
public:
interaction_registration_shape2inst (db::Layout *subject_layout, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, shape_interactions<TS, TI> *result)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result)
interaction_registration_shape2inst (db::Layout *subject_layout, const db::Layout *intruder_layout, unsigned int intruder_layer, unsigned int intruder_layer_index, db::Coord dist, shape_interactions<TS, TI> *result)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_intruder_layer (intruder_layer), m_intruder_layer_index (intruder_layer_index), m_dist (dist), mp_result (result)
{
// nothing yet ..
}
@ -836,7 +836,7 @@ public:
private:
db::Layout *mp_subject_layout;
const db::Layout *mp_intruder_layout;
unsigned int m_intruder_layer;
unsigned int m_intruder_layer, m_intruder_layer_index;
db::Coord m_dist;
shape_interactions<TS, TI> *mp_result;
std::unordered_map<TI, unsigned int> m_inst_shape_ids;
@ -862,7 +862,7 @@ private:
if (k == m_inst_shape_ids.end ()) {
k = m_inst_shape_ids.insert (std::make_pair (ref2, mp_result->next_id ())).first;
mp_result->add_intruder_shape (k->second, m_intruder_layer, ref2);
mp_result->add_intruder_shape (k->second, m_intruder_layer_index, ref2);
}
@ -1686,10 +1686,10 @@ template <class TS, class TI>
struct scan_shape2shape_same_layer
{
void
operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set<TI> &intruders, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set<TI> &intruders, unsigned int intruder_layer_index, shape_interactions<TS, TI> &interactions, db::Coord dist) const
{
db::box_scanner2<TS, int, TI, int> scanner;
interaction_registration_shape1<TS, TI> rec (&interactions, intruder_layer);
interaction_registration_shape1<TS, TI> rec (&interactions, intruder_layer_index);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
@ -1734,10 +1734,10 @@ template <class TS, class TI>
struct scan_shape2shape_different_layers
{
void
operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set<TI> *intruders, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set<TI> *intruders, unsigned int intruder_layer_index, shape_interactions<TS, TI> &interactions, db::Coord dist) const
{
db::box_scanner2<TS, int, TI, int> scanner;
interaction_registration_shape2shape<TS, TI> rec (layout, &interactions, intruder_layer);
interaction_registration_shape2shape<TS, TI> rec (layout, &interactions, intruder_layer_index);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
@ -1790,7 +1790,8 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
}
for (std::vector<unsigned int>::const_iterator il = contexts.intruder_layers ().begin (); il != contexts.intruder_layers ().end (); ++il) {
unsigned int il_index = 0;
for (std::vector<unsigned int>::const_iterator il = contexts.intruder_layers ().begin (); il != contexts.intruder_layers ().end (); ++il, ++il_index) {
const db::Shapes *intruder_shapes = 0;
if (intruder_cell) {
@ -1811,12 +1812,12 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
if (subject_cell == intruder_cell && contexts.subject_layer () == *il) {
scan_shape2shape_same_layer<TS, TI> () (subject_shapes, subject_id0, ipl == intruders.second.end () ? empty_intruders : ipl->second, *il, interactions, op->dist ());
scan_shape2shape_same_layer<TS, TI> () (subject_shapes, subject_id0, ipl == intruders.second.end () ? empty_intruders : ipl->second, il_index, interactions, op->dist ());
} else {
db::Layout *target_layout = (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout);
scan_shape2shape_different_layers<TS, TI> () (target_layout, subject_shapes, intruder_shapes, subject_id0, &(ipl == intruders.second.end () ? empty_intruders : ipl->second), *il, interactions, op->dist ());
scan_shape2shape_different_layers<TS, TI> () (target_layout, subject_shapes, intruder_shapes, subject_id0, &(ipl == intruders.second.end () ? empty_intruders : ipl->second), il_index, interactions, op->dist ());
}
@ -1825,7 +1826,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
if (! subject_shapes->empty () && ! ((! intruder_cell || intruder_cell->begin ().at_end ()) && intruders.first.empty ())) {
db::box_scanner2<TS, int, db::CellInstArray, int> scanner;
interaction_registration_shape2inst<TS, TI> rec (mp_subject_layout, mp_intruder_layout, *il, op->dist (), &interactions);
interaction_registration_shape2inst<TS, TI> rec (mp_subject_layout, mp_intruder_layout, *il, il_index, op->dist (), &interactions);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
@ -2014,11 +2015,12 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
}
}
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
unsigned int il_index = 0;
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il, ++il_index) {
if (*il == subjects) {
scan_shape2shape_same_layer_flat<TS, TI> () ((unsigned int) (il - intruders.begin ()), interactions, op->dist ());
scan_shape2shape_same_layer_flat<TS, TI> () (il_index, interactions, op->dist ());
} else {
scan_shape2shape_different_layers_flat<TS, TI> () (*il, common_box, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
scan_shape2shape_different_layers_flat<TS, TI> () (*il, common_box, il_index, interactions, op->dist ());
}
}

View File

@ -501,7 +501,7 @@ TEST(11_EdgeFilterOperation)
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au11.gds");
}
TEST(12_EdgeBooleanOperations)
void run_test12 (tl::TestBase *_this, bool deep)
{
db::Layout ly;
{
@ -512,14 +512,26 @@ TEST(12_EdgeBooleanOperations)
reader.read (ly);
}
db::DeepShapeStore dss;
db::RegionCheckOptions check_options;
check_options.metrics = db::Projection;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l1));
db::Region r;
if (deep) {
r = db::Region (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l1), dss);
} else {
r = db::Region (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::Region r2;
if (deep) {
r2 = db::Region (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l2), dss);
} else {
r2 = db::Region (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l2));
}
db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode ();
db::CompoundRegionToEdgeProcessingOperationNode *primary_edges = new db::CompoundRegionToEdgeProcessingOperationNode (new db::PolygonToEdgeProcessor (), primary, true);
@ -563,5 +575,19 @@ TEST(12_EdgeBooleanOperations)
res.insert_into (&ly, *ly.begin_top_down (), l1005);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au12.gds");
if (deep) {
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au12d.gds");
} else {
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au12.gds");
}
}
TEST(12_EdgeBooleanOperations)
{
run_test12 (_this, false);
}
TEST(12d_EdgeBooleanOperations)
{
run_test12 (_this, true);
}

BIN
testdata/drc/compound_au12d.gds vendored Normal file

Binary file not shown.