diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 735cd41c0..1210f81b1 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -325,7 +325,7 @@ DeepRegion::not_with (const Region &other) const // Nothing to do return new EmptyRegion (); - } else if (other.empty () && ! strict_handling ()) { + } else if (other.empty ()) { // Nothing to do return clone (); @@ -356,6 +356,73 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const return dl_out; } +RegionDelegate * +DeepRegion::xor_with (const Region &other) const +{ + const DeepRegion *other_deep = dynamic_cast (other.delegate ()); + + if (empty ()) { + + // Nothing to do + return other.delegate ()->clone (); + + } else if (other.empty ()) { + + // Nothing to do + return clone (); + + } else if (! other_deep) { + + return AsIfFlatRegion::xor_with (other); + + } else { + + // Implement XOR as (A-B)+(B-A) - only this implementation + // is compatible with the local processor scheme + DeepLayer n1 (and_or_not_with (other_deep, false)); + DeepLayer n2 (other_deep->and_or_not_with (this, false)); + + std::auto_ptr r (new DeepRegion (n1)); + r->add_from (n2); + return r.release (); + + } +} + +void +DeepRegion::add_from (const DeepLayer &dl) +{ + if (dl.layout () == deep_layer ().layout ()) { + + // intra-layout merge + + deep_layer ().layout ()->copy_layer (dl.layer (), deep_layer ().layer ()); + + } else { + + // inter-layout merge + + db::cell_index_type into_cell = deep_layer ().initial_cell ()->cell_index (); + db::Layout *into_layout = deep_layer ().layout (); + db::cell_index_type source_cell = dl.initial_cell ()->cell_index (); + const db::Layout *source_layout = dl.layout (); + + db::CellMapping cm; + cm.create_from_geometry_full (*into_layout, into_cell, *source_layout, source_cell); + + // Actually copy the shapes + + std::map lm; + lm.insert (std::make_pair (dl.layer (), deep_layer ().layer ())); + + std::vector source_cells; + source_cells.push_back (source_cell); + db::copy_shapes (*into_layout, *source_layout, db::ICplxTrans (), source_cells, cm.table (), lm); + + } +} + + RegionDelegate * DeepRegion::add_in_place (const Region &other) { @@ -366,34 +433,7 @@ DeepRegion::add_in_place (const Region &other) const DeepRegion *other_deep = dynamic_cast (other.delegate ()); if (other_deep) { - if (other_deep->deep_layer ().layout () == deep_layer ().layout ()) { - - // intra-layout merge - - deep_layer ().layout ()->copy_layer (other_deep->deep_layer ().layer (), deep_layer ().layer ()); - - } else { - - // inter-layout merge - - db::cell_index_type into_cell = deep_layer ().initial_cell ()->cell_index (); - db::Layout *into_layout = deep_layer ().layout (); - db::cell_index_type source_cell = other_deep->deep_layer ().initial_cell ()->cell_index (); - const db::Layout *source_layout = other_deep->deep_layer ().layout (); - - db::CellMapping cm; - cm.create_from_geometry_full (*into_layout, into_cell, *source_layout, source_cell); - - // Actually copy the shapes - - std::map lm; - lm.insert (std::make_pair (other_deep->deep_layer ().layer (), deep_layer ().layer ())); - - std::vector source_cells; - source_cells.push_back (source_cell); - db::copy_shapes (*into_layout, *source_layout, db::ICplxTrans (), source_cells, cm.table (), lm); - - } + add_from (other_deep->deep_layer ()); } else { diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 9cdd7df97..8f6c8a909 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -72,6 +72,7 @@ public: virtual RegionDelegate *and_with (const Region &other) const; virtual RegionDelegate *not_with (const Region &other) const; + virtual RegionDelegate *xor_with (const Region &other) const; virtual RegionDelegate *add_in_place (const Region &other); virtual RegionDelegate *add (const Region &other) const; @@ -103,6 +104,7 @@ private: void init (); void ensure_merged_polygons_valid () const; DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const; + void add_from (const DeepLayer &dl); }; } diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index e1a76ecbb..41b148e58 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -241,3 +241,50 @@ TEST(4_Add) db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au4b.gds"); } } + +TEST(5_BoolXOR) +{ + 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 l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l42 = ly.get_layer (db::LayerProperties (42, 0)); + + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + db::Region r42 (db::RecursiveShapeIterator (ly, top_cell, l42), dss); + db::Region box (db::Box (2000, -1000, 6000, 4000)); + + db::Region r2xor3 = r2 ^ r3; + db::Region r2xorbox = r2 ^ box; + db::Region r2xor42 = r2 ^ r42; + db::Region rboxxor3 = box ^ r3; + db::Region r42xor3 = r42 ^ r3; + db::Region r42xor42 = r42 ^ r42; + + 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 (10, 0)), r2xor3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2xorbox); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2xor42); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rboxxor3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r42xor3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r42xor42); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au5.gds"); +} + diff --git a/testdata/algo/deep_region_au5.gds b/testdata/algo/deep_region_au5.gds new file mode 100644 index 000000000..273f7e03e Binary files /dev/null and b/testdata/algo/deep_region_au5.gds differ