diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index b14e1818c..735cd41c0 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -28,6 +28,8 @@ #include "dbShapeProcessor.h" #include "dbFlatRegion.h" #include "dbHierProcessor.h" +#include "dbCellMapping.h" +#include "dbLayoutUtils.h" namespace db { @@ -125,7 +127,7 @@ DeepRegion::~DeepRegion () DeepRegion::DeepRegion (const DeepRegion &other) : AsIfFlatRegion (other), - m_deep_layer (other.m_deep_layer), + m_deep_layer (other.m_deep_layer.copy ()), m_merged_polygons (other.m_merged_polygons), m_merged_polygons_valid (other.m_merged_polygons_valid) { @@ -354,5 +356,72 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const return dl_out; } +RegionDelegate * +DeepRegion::add_in_place (const Region &other) +{ + if (other.empty ()) { + return this; + } + + 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); + + } + + } else { + + // non-deep to deep merge (flat) + + db::Shapes &shapes = deep_layer ().initial_cell ()->shapes (deep_layer ().layer ()); + for (db::Region::const_iterator p = other.begin (); ! p.at_end (); ++p) { + shapes.insert (*p); + } + + } + + return this; + } +RegionDelegate * +DeepRegion::add (const Region &other) const +{ + if (other.empty ()) { + return clone (); + } else if (empty ()) { + return other.delegate ()->clone (); + } else { + DeepRegion *new_region = dynamic_cast (clone ()); + new_region->add_in_place (other); + return new_region; + } +} + +} diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index a69e6ff7f..9cdd7df97 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -73,6 +73,9 @@ public: virtual RegionDelegate *and_with (const Region &other) const; virtual RegionDelegate *not_with (const Region &other) const; + virtual RegionDelegate *add_in_place (const Region &other); + virtual RegionDelegate *add (const Region &other) const; + virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; const DeepLayer &deep_layer () const @@ -80,6 +83,11 @@ public: return m_deep_layer; } + DeepLayer &deep_layer () + { + return m_deep_layer; + } + protected: virtual void merged_semantics_changed (); diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index ed76dbaf5..51d275f23 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -61,6 +61,19 @@ DeepLayer::derived () const return DeepLayer (const_cast (mp_store.get ()), m_layout, const_cast (layout ())->insert_layer ()); } +DeepLayer +DeepLayer::copy () const +{ + DeepLayer new_layer (derived ()); + + db::DeepShapeStore *non_const_store = const_cast (mp_store.get ()); + if (non_const_store->layout (m_layout)) { + non_const_store->layout (m_layout)->copy_layer (m_layer, new_layer.layer ()); + } + + return new_layer; +} + void DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const { diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index e920ad788..9607815b0 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -119,6 +119,11 @@ public: */ DeepLayer derived () const; + /** + * @brief Creates a copy of this layer + */ + DeepLayer copy () const; + /** * @brief Gets the shape store object * This is a pure const version to prevent manipulation of the store. diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 9a15f52d0..e1a76ecbb 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -171,3 +171,73 @@ TEST(3_BoolAndNot) db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au3.gds"); } +TEST(4_Add) +{ + 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 r2box (db::RecursiveShapeIterator (ly, top_cell, l2, box), dss); + db::Region r3box (db::RecursiveShapeIterator (ly, top_cell, l3, box), dss); + + // intra-layout + + { + 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)), r2 + r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r42 + r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2 + r42); + + db::Region rnew2 = r2; + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), rnew2); + rnew2 += r3; + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), rnew2); + rnew2 += r42; + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), rnew2); + + db::Region rnew42 = r42; + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), rnew42); + rnew42 += r2; + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), rnew42); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au4a.gds"); + } + + // inter-layout + + { + 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)), r2box + r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2 + r3box); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2box + r3box); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), box + r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2 + box); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au4b.gds"); + } +} diff --git a/testdata/algo/deep_region_au4a.gds b/testdata/algo/deep_region_au4a.gds new file mode 100644 index 000000000..d87d595f7 Binary files /dev/null and b/testdata/algo/deep_region_au4a.gds differ diff --git a/testdata/algo/deep_region_au4b.gds b/testdata/algo/deep_region_au4b.gds new file mode 100644 index 000000000..8947f5e02 Binary files /dev/null and b/testdata/algo/deep_region_au4b.gds differ