From b28317fb69416337e5e80478b221eeeaa5e842fd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 30 Aug 2017 01:11:38 +0200 Subject: [PATCH] Some enhancements to layer and cell mapping * Modification of the mapping is possible now (#map used to ignore mappings if there was one already) * Added DropCell mapping (also for RBA) * Added unit tests for cell mapping, layer mapping db::merge_layouts, db::copy_shapes and db::move_shapes --- src/db/db/dbCellMapping.h | 2 +- src/db/db/dbLayerMapping.h | 2 +- src/db/db/dbLayoutUtils.cc | 110 +++-- src/db/db/dbLayoutUtils.h | 9 + src/db/db/gsiDeclDbCellMapping.cc | 50 ++- src/db/unit_tests/dbLayoutUtils.cc | 616 +++++++++++++++++++++++++++ src/db/unit_tests/unit_tests.pro | 1 + testdata/algo/layout_utils_au12.gds | Bin 0 -> 1830 bytes testdata/algo/layout_utils_au13.gds | Bin 0 -> 1174 bytes testdata/algo/layout_utils_au14.gds | Bin 0 -> 1298 bytes testdata/algo/layout_utils_au15.gds | Bin 0 -> 1254 bytes testdata/algo/layout_utils_au16.gds | Bin 0 -> 1856 bytes testdata/algo/layout_utils_au16b.gds | Bin 0 -> 464 bytes testdata/algo/layout_utils_au2.gds | Bin 0 -> 1596 bytes testdata/algo/layout_utils_au3.gds | Bin 0 -> 1596 bytes testdata/algo/layout_utils_au4.gds | Bin 0 -> 1174 bytes testdata/algo/layout_utils_au5.gds | Bin 0 -> 1298 bytes testdata/algo/layout_utils_au6.gds | Bin 0 -> 1256 bytes testdata/algo/layout_utils_au7.gds | Bin 0 -> 1572 bytes testdata/algo/layout_utils_l1.gds | Bin 0 -> 864 bytes testdata/algo/layout_utils_l2.gds | Bin 0 -> 924 bytes testdata/algo/layout_utils_l3.gds | Bin 0 -> 800 bytes testdata/ruby/dbCellMapping.rb | 14 +- testdata/ruby/dbLayerMapping.rb | 2 + 24 files changed, 746 insertions(+), 60 deletions(-) create mode 100644 src/db/unit_tests/dbLayoutUtils.cc create mode 100644 testdata/algo/layout_utils_au12.gds create mode 100644 testdata/algo/layout_utils_au13.gds create mode 100644 testdata/algo/layout_utils_au14.gds create mode 100644 testdata/algo/layout_utils_au15.gds create mode 100644 testdata/algo/layout_utils_au16.gds create mode 100644 testdata/algo/layout_utils_au16b.gds create mode 100644 testdata/algo/layout_utils_au2.gds create mode 100644 testdata/algo/layout_utils_au3.gds create mode 100644 testdata/algo/layout_utils_au4.gds create mode 100644 testdata/algo/layout_utils_au5.gds create mode 100644 testdata/algo/layout_utils_au6.gds create mode 100644 testdata/algo/layout_utils_au7.gds create mode 100644 testdata/algo/layout_utils_l1.gds create mode 100644 testdata/algo/layout_utils_l2.gds create mode 100644 testdata/algo/layout_utils_l3.gds diff --git a/src/db/db/dbCellMapping.h b/src/db/db/dbCellMapping.h index a6b1f24a4..77b134d6e 100644 --- a/src/db/db/dbCellMapping.h +++ b/src/db/db/dbCellMapping.h @@ -144,7 +144,7 @@ public: */ void map (db::cell_index_type cell_index_b, db::cell_index_type cell_index_a) { - m_b2a_mapping.insert (std::make_pair (cell_index_b, cell_index_a)); + m_b2a_mapping.insert (std::make_pair (cell_index_b, 0)).first->second = cell_index_a; } /** diff --git a/src/db/db/dbLayerMapping.h b/src/db/db/dbLayerMapping.h index 8e0942386..7729d0739 100644 --- a/src/db/db/dbLayerMapping.h +++ b/src/db/db/dbLayerMapping.h @@ -102,7 +102,7 @@ public: */ void map (unsigned int layer_b, unsigned int layer_a) { - m_b2a_mapping.insert (std::make_pair (layer_b, layer_a)); + m_b2a_mapping.insert (std::make_pair (layer_b, 0)).first->second = layer_a; } /** diff --git a/src/db/db/dbLayoutUtils.cc b/src/db/db/dbLayoutUtils.cc index a41cef07e..1e37a2f59 100644 --- a/src/db/db/dbLayoutUtils.cc +++ b/src/db/db/dbLayoutUtils.cc @@ -126,6 +126,40 @@ PropertyMapper::operator() (db::Layout::properties_id_type source_id) // ------------------------------------------------------------------------------------ // merge_layouts implementation +static void +collect_cells_to_copy (const db::Layout &source, + const std::vector &source_cells, + const std::map &cell_mapping, + std::set &all_top_level_cells, + std::set &all_cells_to_copy) +{ + std::vector dropped_cells; + + for (std::map::const_iterator m = cell_mapping.begin (); m != cell_mapping.end (); ++m) { + if (m->second == DropCell) { + dropped_cells.push_back (m->first); + } + } + + for (std::vector::const_iterator src = source_cells.begin (); src != source_cells.end (); ++src) { + + all_cells_to_copy.insert (*src); + all_top_level_cells.insert (*src); + + // feed the excluded cells into the "all_cells_to_copy" cache. This will make "collect_called_cells" not + // dive into their hierarchy. We will later delete them there. + all_cells_to_copy.insert (dropped_cells.begin (), dropped_cells.end ()); + + source.cell (*src).collect_called_cells (all_cells_to_copy); + + for (std::vector::const_iterator i = dropped_cells.begin (); i != dropped_cells.end (); ++i) { + all_cells_to_copy.erase (*i); + all_top_level_cells.erase (*i); + } + + } +} + void merge_layouts (db::Layout &target, const db::Layout &source, @@ -135,19 +169,11 @@ merge_layouts (db::Layout &target, const std::map &layer_mapping, std::map *final_cell_mapping) { - if (final_cell_mapping) { - final_cell_mapping->insert (cell_mapping.begin (), cell_mapping.end ()); - } - // collect all called cells and all top level cells std::set all_top_level_cells; std::set all_cells_to_copy; - for (std::vector::const_iterator src = source_cells.begin (); src != source_cells.end (); ++src) { - all_cells_to_copy.insert (*src); - all_top_level_cells.insert (*src); - source.cell (*src).collect_called_cells (all_cells_to_copy); - } + collect_cells_to_copy (source, source_cells, cell_mapping, all_top_level_cells, all_cells_to_copy); // identify all new cells and create new ones std::map new_cell_mapping; @@ -158,6 +184,11 @@ merge_layouts (db::Layout &target, } if (final_cell_mapping) { + for (std::map::const_iterator m = cell_mapping.begin (); m != cell_mapping.end (); ++m) { + if (m->second != DropCell) { + final_cell_mapping->insert (*m); + } + } final_cell_mapping->insert (new_cell_mapping.begin (), new_cell_mapping.end ()); } @@ -248,7 +279,7 @@ copy_or_propagate_shapes (db::Layout &target, } - } else { + } else if (cm->second != DropCell) { db::Cell &target_cell = target.cell (cm->second); target_cell.shapes (target_layer).insert_transformed (source_cell.shapes (source_layer), trans * propagate_trans, pm); @@ -256,23 +287,20 @@ copy_or_propagate_shapes (db::Layout &target, } } -void -copy_shapes (db::Layout &target, - const db::Layout &source, - const db::ICplxTrans &trans, - const std::vector &source_cells, - const std::map &cell_mapping, - const std::map &layer_mapping) +static void +copy_or_move_shapes (db::Layout &target, + db::Layout &source, + const db::ICplxTrans &trans, + const std::vector &source_cells, + const std::map &cell_mapping, + const std::map &layer_mapping, + bool move) { // collect all called cells and all top level cells std::set all_top_level_cells; std::set all_cells_to_copy; - for (std::vector::const_iterator src = source_cells.begin (); src != source_cells.end (); ++src) { - all_cells_to_copy.insert (*src); - all_top_level_cells.insert (*src); - source.cell (*src).collect_called_cells (all_cells_to_copy); - } + collect_cells_to_copy (source, source_cells, cell_mapping, all_top_level_cells, all_cells_to_copy); // provide the property mapper db::PropertyMapper pm (target, source); @@ -284,10 +312,24 @@ copy_shapes (db::Layout &target, for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { ++progress; copy_or_propagate_shapes (target, source, trans, db::ICplxTrans (), pm, *c, *c, lm->second, lm->first, all_cells_to_copy, cell_mapping); + if (move) { + source.cell (*c).shapes (lm->first).clear (); + } } } } +void +copy_shapes (db::Layout &target, + const db::Layout &source, + const db::ICplxTrans &trans, + const std::vector &source_cells, + const std::map &cell_mapping, + const std::map &layer_mapping) +{ + copy_or_move_shapes (target, const_cast (source), trans, source_cells, cell_mapping, layer_mapping, false); +} + void move_shapes (db::Layout &target, db::Layout &source, @@ -296,29 +338,7 @@ move_shapes (db::Layout &target, const std::map &cell_mapping, const std::map &layer_mapping) { - // collect all called cells and all top level cells - std::set all_top_level_cells; - std::set all_cells_to_copy; - - for (std::vector::const_iterator src = source_cells.begin (); src != source_cells.end (); ++src) { - all_cells_to_copy.insert (*src); - all_top_level_cells.insert (*src); - source.cell (*src).collect_called_cells (all_cells_to_copy); - } - - // provide the property mapper - db::PropertyMapper pm (target, source); - - tl::RelativeProgress progress (tl::to_string (QObject::tr ("Merge cells")), all_cells_to_copy.size () * layer_mapping.size (), 1); - - // and copy - for (std::set::const_iterator c = all_cells_to_copy.begin (); c != all_cells_to_copy.end (); ++c) { - for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { - ++progress; - copy_or_propagate_shapes (target, source, trans, db::ICplxTrans (), pm, *c, *c, lm->second, lm->first, all_cells_to_copy, cell_mapping); - source.cell (*c).shapes (lm->first).clear (); - } - } + copy_or_move_shapes (target, source, trans, source_cells, cell_mapping, layer_mapping, true); } // ------------------------------------------------------------ diff --git a/src/db/db/dbLayoutUtils.h b/src/db/db/dbLayoutUtils.h index 65e59668a..b821e0008 100644 --- a/src/db/db/dbLayoutUtils.h +++ b/src/db/db/dbLayoutUtils.h @@ -32,6 +32,7 @@ #include #include +#include namespace db { @@ -110,6 +111,14 @@ private: std::map m_prop_id_map; }; +/** + * @brief A constant describing "drop cell" mapping + * + * If used as the target cell index, this constant means "drop the cell". + * This cell and it's children will be dropped unless the children are used by other cells. + */ +const db::cell_index_type DropCell = std::numeric_limits::max (); + /** * @brief Merge one layout into another * diff --git a/src/db/db/gsiDeclDbCellMapping.cc b/src/db/db/gsiDeclDbCellMapping.cc index 035bcd25c..935ef25cf 100644 --- a/src/db/db/gsiDeclDbCellMapping.cc +++ b/src/db/db/gsiDeclDbCellMapping.cc @@ -23,6 +23,7 @@ #include "gsiDecl.h" #include "dbCellMapping.h" +#include "dbLayoutUtils.h" #include "dbLayout.h" #include @@ -30,9 +31,25 @@ namespace gsi { +static db::cell_index_type drop_cell_const () +{ + return db::DropCell; +} + Class decl_CellMapping ("CellMapping", + gsi::method ("DropCell", &drop_cell_const, + "@brief A constant indicating the reques to drop a cell\n" + "\n" + "If used as a pseudo-target for the cell mapping, this index indicates " + "that the cell shall be dropped rather than created on the target side " + "or skipped by flattening. Instead, all shapes of this cell are discarded " + "and it's children are not translated unless explicitly requested or " + "if required are children for other cells.\n" + "\n" + "This constant has been introduced in version 0.25." + ) + gsi::method ("for_single_cell", &db::CellMapping::create_single_mapping, - "@brief Initialize the cell mapping for top-level identity\n" + "@brief Initializes the cell mapping for top-level identity\n" "\n" "@args layout_a, cell_index_a, layout_b, cell_index_b\n" "@param layout_a The target layout.\n" @@ -42,13 +59,15 @@ Class decl_CellMapping ("CellMapping", "\n" "The cell mapping is created for cell_b to cell_a in the respective layouts. " "This method clears the mapping and creates one for the single cell pair. " - "In addition, this method completes the mapping by adding all the child cells " - "of cell_b to layout_a and creating the proper instances. " + "If used for \\Cell#copy_tree or \\Cell#move_tree, this cell mapping will essentially " + "flatten the cell.\n" + "\n" + "This method is equivalent to \\clear, followed by \\map(cell_index_a, cell_index_b).\n" "\n" "This method has been introduced in version 0.23." ) + gsi::method ("for_single_cell_full", &db::CellMapping::create_single_mapping_full, - "@brief Initialize the cell mapping for top-level identity\n" + "@brief Initializes the cell mapping for top-level identity\n" "\n" "@args layout_a, cell_index_a, layout_b, cell_index_b\n" "@param layout_a The target layout.\n" @@ -58,11 +77,13 @@ Class decl_CellMapping ("CellMapping", "\n" "The cell mapping is created for cell_b to cell_a in the respective layouts. " "This method clears the mapping and creates one for the single cell pair. " + "In addition and in contrast to \\for_single_cell, this method completes the mapping by adding all the child cells " + "of cell_b to layout_a and creating the proper instances. " "\n" "This method has been introduced in version 0.23." ) + gsi::method ("from_geometry_full", &db::CellMapping::create_from_geometry_full, - "@brief Initialize the cell mapping using the geometrical identity in full mapping mode\n" + "@brief Initializes the cell mapping using the geometrical identity in full mapping mode\n" "\n" "@args layout_a, cell_index_a, layout_b, cell_index_b\n" "@param layout_a The target layout.\n" @@ -83,7 +104,7 @@ Class decl_CellMapping ("CellMapping", "This method has been introduced in version 0.23." ) + gsi::method ("from_geometry", &db::CellMapping::create_from_geometry, - "@brief Initialize the cell mapping using the geometrical identity\n" + "@brief Initializes the cell mapping using the geometrical identity\n" "\n" "@args layout_a, cell_index_a, layout_b, cell_index_b\n" "@param layout_a The target layout.\n" @@ -99,7 +120,7 @@ Class decl_CellMapping ("CellMapping", "This method has been introduced in version 0.23." ) + gsi::method ("from_names", &db::CellMapping::create_from_names, - "@brief Initialize the cell mapping using the name identity\n" + "@brief Initializes the cell mapping using the name identity\n" "\n" "@args layout_a, cell_index_a, layout_b, cell_index_b\n" "@param layout_a The target layout.\n" @@ -114,7 +135,7 @@ Class decl_CellMapping ("CellMapping", "This method has been introduced in version 0.23." ) + gsi::method ("from_names_full", &db::CellMapping::create_from_names_full, - "@brief Initialize the cell mapping using the name identity in full mapping mode\n" + "@brief Initializes the cell mapping using the name identity in full mapping mode\n" "\n" "@args layout_a, cell_index_a, layout_b, cell_index_b\n" "@param layout_a The target layout.\n" @@ -139,12 +160,12 @@ Class decl_CellMapping ("CellMapping", "This method has been introduced in version 0.23." ) + gsi::method ("map", &db::CellMapping::map, - "@brief Explicitly specify a mapping.\n" + "@brief Explicitly specifies a mapping.\n" "\n" "@args cell_index_b, cell_index_a\n" "\n" "@param cell_index_b The index of the cell in layout B (the \"source\")\n" - "@param cell_index_a The index of the cell in layout A (the \"target\")\n" + "@param cell_index_a The index of the cell in layout A (the \"target\") - this index can be \\DropCell\n" "\n" "Beside using the mapping generator algorithms provided through \\from_names and \\from_geometry, " "it is possible to explicitly specify cell mappings using this method.\n" @@ -152,20 +173,25 @@ Class decl_CellMapping ("CellMapping", "This method has been introduced in version 0.23." ) + gsi::method ("has_mapping?", &db::CellMapping::has_mapping, - "@brief Determine if a cell of layout_b has a mapping to a layout_a cell.\n" + "@brief Returns as value indicating whether a cell of layout_b has a mapping to a layout_a cell.\n" "\n" "@args cell_index_b\n" "\n" "@param cell_index_b The index of the cell in layout_b whose mapping is requested.\n" "@return true, if the cell has a mapping\n" + "\n" + "Note that if the cell is supposed to be dropped (see \\DropCell), the respective " + "source cell will also be regarded \"mapped\", so has_mapping? will return true in this case.\n" ) + gsi::method ("cell_mapping", &db::CellMapping::cell_mapping, - "@brief Determine cell mapping of a layout_b cell to the corresponding layout_a cell.\n" + "@brief Determines cell mapping of a layout_b cell to the corresponding layout_a cell.\n" "\n" "@args cell_index_b\n" "\n" "@param cell_index_b The index of the cell in layout_b whose mapping is requested.\n" "@return The cell index in layout_a.\n" + "\n" + "Note that the returned index can be \\DropCell to indicate the cell shall be dropped." ), "@brief A cell mapping (source to target layout)\n" "\n" diff --git a/src/db/unit_tests/dbLayoutUtils.cc b/src/db/unit_tests/dbLayoutUtils.cc new file mode 100644 index 000000000..b09633e8d --- /dev/null +++ b/src/db/unit_tests/dbLayoutUtils.cc @@ -0,0 +1,616 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 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 "dbLayoutUtils.h" +#include "dbLayerMapping.h" +#include "dbCellMapping.h" +#include "dbReader.h" +#include "tlString.h" +#include "utHead.h" + +unsigned int find_layer (const db::Layout &l, int ly, int dt) +{ + for (db::Layout::layer_iterator li = l.begin_layers (); li != l.end_layers (); ++li) { + if ((*li).second->log_equal (db::LayerProperties (ly, dt))) { + return (*li).first; + } + } + tl_assert (false); +} + +TEST(1) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + db::LayerMapping lm; + lm.create (l2, l1); + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + EXPECT_EQ (lm.has_mapping (li1), true); + EXPECT_EQ (lm.layer_mapping_pair (li1).first, true); + EXPECT_EQ (l2.get_properties (lm.layer_mapping_pair (li1).second).to_string (), "1/0"); + EXPECT_EQ (lm.has_mapping (li2), true); + EXPECT_EQ (lm.layer_mapping_pair (li2).first, true); + EXPECT_EQ (l2.get_properties (lm.layer_mapping_pair (li2).second).to_string (), "2/0"); + EXPECT_EQ (lm.has_mapping (li3), false); + EXPECT_EQ (lm.layer_mapping_pair (li3).first, false); + + lm.clear (); + EXPECT_EQ (lm.has_mapping (li1), false); + EXPECT_EQ (lm.has_mapping (li2), false); + EXPECT_EQ (lm.has_mapping (li3), false); + + lm.create_full (l2, l1); + + EXPECT_EQ (lm.has_mapping (li1), true); + EXPECT_EQ (lm.layer_mapping_pair (li1).first, true); + EXPECT_EQ (l2.get_properties (lm.layer_mapping_pair (li1).second).to_string (), "1/0"); + EXPECT_EQ (lm.has_mapping (li2), true); + EXPECT_EQ (lm.layer_mapping_pair (li2).first, true); + EXPECT_EQ (l2.get_properties (lm.layer_mapping_pair (li2).second).to_string (), "2/0"); + EXPECT_EQ (lm.has_mapping (li3), true); + EXPECT_EQ (lm.layer_mapping_pair (li3).first, true); + EXPECT_EQ (l2.get_properties (lm.layer_mapping_pair (li3).second).to_string (), "3/0"); +} + +// Tests merge_layout with no specific mapping (plain duplication of the tree) +TEST(2) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::map fm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + db::merge_layouts (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table (), &fm); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au2.gds"); + + EXPECT_EQ (fm.find (l1.cell_by_name ("TOP").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("TOP").second)->second), "TOP$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("A").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("A").second)->second), "A$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("B").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("B").second)->second), "B$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("C").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("C").second)->second), "C$1"); +} + +// Tests merge_layout with a single mapped cell (the others are mapped automatically) +TEST(3) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::map fm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.map (src.front (), l2.add_cell ("TOPTOP")); + db::merge_layouts (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table (), &fm); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au3.gds"); + + EXPECT_EQ (fm.find (l1.cell_by_name ("TOP").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("TOP").second)->second), "TOPTOP"); + EXPECT_EQ (fm.find (l1.cell_by_name ("A").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("A").second)->second), "A$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("B").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("B").second)->second), "B$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("C").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("C").second)->second), "C$1"); +} + +// Tests merge_layout with a mapped tree (by name) +TEST(4) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.create_from_names_full (l2, l2.cell_by_name ("TOP").second, l1, src.front ()); + std::map fm; + db::merge_layouts (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table (), &fm); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au4.gds"); + + EXPECT_EQ (fm.find (l1.cell_by_name ("TOP").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("TOP").second)->second), "TOP"); + EXPECT_EQ (fm.find (l1.cell_by_name ("A").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("A").second)->second), "A"); + EXPECT_EQ (fm.find (l1.cell_by_name ("B").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("B").second)->second), "B"); + EXPECT_EQ (fm.find (l1.cell_by_name ("C").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("C").second)->second), "C"); +} + +// Tests merge_layout with a equivalence-mapped tree +TEST(5) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.create_from_geometry_full (l2, l2.cell_by_name ("TOP").second, l1, src.front ()); + std::map fm; + db::merge_layouts (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table (), &fm); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au5.gds"); + + EXPECT_EQ (fm.find (l1.cell_by_name ("TOP").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("TOP").second)->second), "TOP"); + EXPECT_EQ (fm.find (l1.cell_by_name ("A").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("A").second)->second), "A"); + EXPECT_EQ (fm.find (l1.cell_by_name ("B").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("B").second)->second), "B"); + EXPECT_EQ (fm.find (l1.cell_by_name ("C").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("C").second)->second), "C$1"); +} + +// Tests merge_layout with dropping of cell B +TEST(6) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + // Drop cell B + cm.map (l1.cell_by_name ("B").second, db::DropCell); + cm.map (l1.cell_by_name ("TOP").second, l2.cell_by_name ("TOP").second); + + std::map fm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + db::merge_layouts (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table (), &fm); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au6.gds"); + + EXPECT_EQ (fm.find (l1.cell_by_name ("TOP").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("TOP").second)->second), "TOP"); + EXPECT_EQ (fm.find (l1.cell_by_name ("A").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("A").second)->second), "A$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("B").second) != fm.end (), false); + EXPECT_EQ (fm.find (l1.cell_by_name ("C").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("C").second)->second), "C$1"); +} + +// Tests merge_layout with transformation +TEST(7) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l3.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::Layout l2copy = l2; + + db::CellMapping cm; + cm.map (l1.cell_by_name ("TOP").second, l2.cell_by_name ("TOP").second); + + std::map fm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + db::merge_layouts (l2, l1, db::ICplxTrans (4.0), src, cm.table (), lm.table (), &fm); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au7.gds"); + + EXPECT_EQ (fm.find (l1.cell_by_name ("TOP").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("TOP").second)->second), "TOP"); + EXPECT_EQ (fm.find (l1.cell_by_name ("A").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("A").second)->second), "A$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("B").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("B").second)->second), "B$1"); + EXPECT_EQ (fm.find (l1.cell_by_name ("C").second) != fm.end (), true); + EXPECT_EQ (l2.cell_name (fm.find (l1.cell_by_name ("C").second)->second), "C"); + + // Once with final_mapping = 0 ... + db::merge_layouts (l2copy, l1, db::ICplxTrans (4.0), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2copy, ut::testsrc () + "/testdata/algo/layout_utils_au7.gds"); +} + +// Tests copy_shapes with no specific mapping (flattening) +TEST(12) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::map fm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.map (src.front (), l2.cell_by_name ("TOP").second); + db::copy_shapes (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au12.gds"); +} + +// Tests copy_shapes with full name mapping +TEST(13) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.create_from_names_full (l2, l2.cell_by_name ("TOP").second, l1, src.front ()); + db::copy_shapes (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au13.gds"); +} + +// Tests copy_shapes with geo mapping +TEST(14) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.create_from_geometry_full (l2, l2.cell_by_name ("TOP").second, l1, src.front ()); + db::copy_shapes (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au14.gds"); +} + +// Tests copy_shapes with flattening minus one cell +TEST(15) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l2.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::CellMapping cm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.map (src.front (), l2.cell_by_name ("TOP").second); + cm.map (l1.cell_by_name ("B").second, db::DropCell); + db::copy_shapes (l2, l1, db::ICplxTrans (), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au15.gds"); +} + +// Tests copy_shapes/move_shapes with no specific mapping (flattening) +TEST(16) +{ + db::Layout l1; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l1); + } + + db::Layout l2; + { + std::string fn (ut::testsrc ()); + fn += "/testdata/algo/layout_utils_l3.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (l2); + } + + unsigned int li1 = find_layer (l1, 1, 0); + unsigned int li2 = find_layer (l1, 2, 0); + unsigned int li3 = find_layer (l1, 3, 0); + + db::LayerMapping lm; + lm.map (li1, l2.insert_layer (db::LayerProperties (11, 0))); + lm.map (li2, l2.insert_layer (db::LayerProperties (12, 0))); + lm.map (li3, l2.insert_layer (db::LayerProperties (13, 0))); + + db::Layout l2copy = l2; + + db::CellMapping cm; + std::map fm; + std::vector src; + src.push_back (l1.cell_by_name ("TOP").second); + cm.map (src.front (), l2.cell_by_name ("TOP").second); + db::copy_shapes (l2, l1, db::ICplxTrans (4.0), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2, ut::testsrc () + "/testdata/algo/layout_utils_au16.gds"); + + // ... and one test for move: + db::move_shapes (l2copy, l1, db::ICplxTrans (4.0), src, cm.table (), lm.table ()); + + CHECKPOINT(); + compare_layouts (l2copy, ut::testsrc () + "/testdata/algo/layout_utils_au16.gds"); + compare_layouts (l1, ut::testsrc () + "/testdata/algo/layout_utils_au16b.gds"); + +} + diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index 0488daec9..c167b1056 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -31,6 +31,7 @@ SOURCES = \ dbLayerMapping.cc \ dbLayout.cc \ dbLayoutDiff.cc \ + dbLayoutUtils.cc \ dbLayoutQuery.cc \ dbLibraries.cc \ dbMatrix.cc \ diff --git a/testdata/algo/layout_utils_au12.gds b/testdata/algo/layout_utils_au12.gds new file mode 100644 index 0000000000000000000000000000000000000000..4495e1dbeb60bc481d7e61e732f39e2e317be688 GIT binary patch literal 1830 zcmc&#J#Q015S{zlJAsWzWTl9lh#z2y649X8q=~RZ3Kvm+13w@|$~5UHk!a}Brl6pp zMwI*j8oHDe`2oB)J9D=-TE$&Xvfp{%zM0uKv$6y!%QKl4W&1}uITVot*-PK0E5q_+ zAu_3&H}mUP?|$6;eSQ4x<(JRrE15QVT?pZ=NZpBqaVdp_XC%xzo?<4FeiEwQ zfxeZ8vdsU_a=DqM`7Kg@7jY~;;`bRc8#Win`xCrjbr(5D?j!HWcgE{+D0|DQ;b{E? z-t5w)5$mN3cvRm-*UGGGs7GBh9Mb3Ysmp%u9)~V$Q-2r2>iubd0(3x6U{z>@cs4L$ zzrgxv+APkE*S*~*k?KXPHtvNZ%FtKTl|%tEMEROV2}ijoWY(j&&+J*fT=VIv`TXc} zV|`z%hkn4RetuhQ;v6etUdeH8iJaH^c0j&!pCkG9SLBI|!%jGQ9$-3$UeAnk>UV;u zcWN>q=gIi2zWtz`5hC@>??}DzS-r-;k9qX$$nRL#IxwrZ{`dEt8u~}XT`A6wJ=2>}8BI{O-p|1n8dhS;(b3w=4j=m1e>g{F-kvjVA$o$4< z_1-tv*-h^IXna=BdYQ-T_By;SzQooBj(Pdc`_ezoV}MH9!7+ H>RSE*7VD+J literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_au13.gds b/testdata/algo/layout_utils_au13.gds new file mode 100644 index 0000000000000000000000000000000000000000..6cb74050a4efbaf0202426c28c24cdb00cfd068c GIT binary patch literal 1174 zcmc&yJ5Izf6dXJDTMM!X5EY6L4c$tVhz79>4PqrIwpi^+D7XL}B@zuC7oeb^MjV2M zj*=tro@2)jB8q?lOUXDHzmI1g2wKlkDLr_D!xn%YRQVoG)AVElY!voje6@G_eE+e3 z{J48}yO^P}-El;81Q-Xkf@@tp& z70^#WM0L&IbM8E#z2LrIm=9RI*IYz7CwxTNOTGrvwZFUdzxUIxB2S1}Vz1Z5^-}Z` zS9#_4(VZ@`K7I-UCONv}^QnnGG?=C;uV4PLek=Yb^?USlM6y~APyz&48b8CIG8Ne@^{vxDyS-s#K3 z$Nurt&i&nJfFf%+XUx&oE}$)7+6s#>ON#uR<&@viN;*LNi6Fhg^DQ*?G3--yN&c=& zce=~v*IBYRKs^JYCO7;&A1Dr=R?SnK?k{cGoc z(tnP&)|kQBd8sbb>J;=U1a+x95wo7~|Gdb0Bagei_7+GtODDLOZaG9UNL?ZpA{EPH z%wi5_u?SLU2^o-l>wd{!%Rm#BUa{A>=5IUp$GtneoWDP0Lh)CsERVansIS)e1hj!- A5&!@I literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_au15.gds b/testdata/algo/layout_utils_au15.gds new file mode 100644 index 0000000000000000000000000000000000000000..6a897097dffe5c7b434053230bc10a81bd470088 GIT binary patch literal 1254 zcmc&!p-uxq6r9_;+q*zZfK-tS!Qh%835L*uAv6I|(ez6YNDK~1g27=C2n3o`@&One z62S-X=I!p?7ILAEO?tC;v+upx*|&v-F%wjYDc(_H6TmjAc#hK8(eV)IrTPBgYWL*j z{&Vl>Y3J^CI!2YZ$60F+fvf~<*C2siF_OK%n#wa8Ngs%R5tXe;e1X5J41QO+_*o@? z1I#lJFu9iZiB$HOpG)1D@E+3-#|7j%@&P$#z8V|Z3#t}JvnBCnoi25#moCWA_|my% zT3r)8>YB%~}^i_04S%hh_JjPk?Qpk^P!IG{`yE1ted*I-bZpJc)pzj$qt}K~G=r)lB`X?@RLK>J!CR{odlQ q#;2FAJ~8h(Z2_sz^Kt!dd=K>ANg3ZKs-Jz#eQ zw3TxfWts7M^iO}bO7cB^(G))%r1QeaOs__Mu9v(w=N8^Evqk>v`VS{6Ri*E$ii-m?AP zurvDV_IURFxo!SPJxXUs?uEKcXXeE$6EC;9mo>Vs^+L*^El zHGOcxh}5=nIzjELCzTzw|AOip`R{HLpGZFA3(0r;i}AbnDL(ZwzEJyyjeMVs@l7I! z^&{HE#C=UpoqnGm5E+}b6|yEZ^VQ4$OU#vd5~-UUq4sC$H^o=o#mn=jPq*j!Px1ZE zz;9KoH{+`>`JM9or}*j{kvzZS<375*F+TM&PwAEp>2iA`pZSqbWY2hBsQsDxEzH&* Uw$umeCy&U*eOocU{nyJ9&mHiluK)l5 literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_au16b.gds b/testdata/algo/layout_utils_au16b.gds new file mode 100644 index 0000000000000000000000000000000000000000..3816a5a37a8acfcede0475a672750bc72b0e8b2c GIT binary patch literal 464 zcmZQzV_;&6V31*CVt>fM!63)Lz+l3ljLc@>U}E#}bYfr-VP>^+>@@d2w)}&o%MSeo zv!g;7WLR7nw?1c z&O9$bVat3je|pKv--tUKPi#$v)%P`CSpBWzmDV@DNZp)p{(Zv#plWVSLcIv}0?bp3 z`k`8;{C`m`O_9;rd7yct9n*yypP8NA2ZPCGM5NV82V-}`+|KTRc*kyty=^whU|JPa zNf60kKGIVdN&536X>2-@`TN*h=6e3UvKgD5jB5-F6ccemh>f8->=7tA(!vH$=8 literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_au3.gds b/testdata/algo/layout_utils_au3.gds new file mode 100644 index 0000000000000000000000000000000000000000..63692e20b3f4c1af8b9dfbe7854320f004da6f54 GIT binary patch literal 1596 zcmdT^Jxc>Y5Pi3IH#uS=DuN&p6l{cmScy$A(MAktkwWrIEG%v8ECm}o|A2*swfG}! z>{9v@e6zQg-NefgPz#sj=HSiF$D20?fiV|oMW*(F3>#R(7IwmSWJdZYJzzCXJKdZ8 z)7Qt(gX8Djhx_3Gt+e8v$kFy5kYs=~4Hh7a20(i$<})}^8wmdalq~ap4V8I>d3=`W zkFsPUJ=;wk$X4>s8rq3g&SNWeoi=9HaO*mCcDmED`yn$C?{QifThH7)OtFV<*+j0U zCz8H1&kIo4aXyzny=3KY#GQ>tc};~?f5i){?;3AxedF`g%?WqEPxv2H&8!QpY4H~x7x8?xbfN9<@;bUS&xV`T4`_SJgj$i2gIBChUDIM zlPspHph|*B7W0vw!boyBJCb6Pk?hweub28u`e7E2#n+5En%LiFI1#H`7U3#|cB8sh ztH324+rXPVOV;ToAOLqg1;0h8$bizz%lPJ#tOclQFQK*~8J*{^|4m z$HC-r@9uUnLuuRNi0BwFIY5041zOPnhN~IBlck10`XrQDi}B09jqjnW%TcTny1e|_ zrF{kT6A(~c^Y@%P_h>J;?-%AhX73djP|gV-Q1+6q#(3@TZvF55bgRe{VwTwJfw*3X ze&Q;x^gg=PMb^hnfyXFEdwe=I!G{{-RHgNcKh|%=|D=A0emT+X?7UWxC(;2Q0 zhmV8fr``LzVIO%qYx+(+f`bNe~MMedc?` zB$)-?dR1J@L_hJK%g;l`k&)a?aA8(8)nRJqa}=+#>J1^B`TD^ing+g8GPR4E|{6EXn?lACvue$~GR_O%y(k;(O2B}L_g-liD zF|K0U)2awluTo?{@@;x${aOZQar%nAMm2w%u|NLZ;pM{pArp$fg0ced=c2yG;1dw= BVk!Ut literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_au6.gds b/testdata/algo/layout_utils_au6.gds new file mode 100644 index 0000000000000000000000000000000000000000..f33de698321cad73a2982afc43136e3a5559ead8 GIT binary patch literal 1256 zcmd5*yGjE=6g@jTdoySv8U!Iku&@k>m53m2Vj~8$ND=ZS7M3=4mV%9)KVV^DEq;WJ zT}nT}d*`t;(QHUz;lS?Q-7|CUEYpE@i=*(Z32@+^E+jD;^*_h4S#e?1>op^VcB zD*X59aMkQMy~5sUi;J3~rnrQcovv}NQnjvPwXCarjN;UvPhA*XQN`%eCDk2WTvi>h z0=5HRg=KKPF+!b;zc;%@f8uew*W3g7j;q$~<%w8CT*q}KEQ~~!=ahv`>R1GsWeIZ@ zN9$q5Z`$q;o7X|WV)jKn@NVmQ$Mh>p#PS=idOD+2D^=S5cig6*1Y}mCltft`4@zl` EZ$qYJyZ`_I literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_au7.gds b/testdata/algo/layout_utils_au7.gds new file mode 100644 index 0000000000000000000000000000000000000000..e5f87462cc22466b3642fdbba67e2f127aca9b2d GIT binary patch literal 1572 zcmd5+y-EW?5dN~c+no8)Bq*W;5fLj9Ei7!r+*N|2g@srJpTGyO@F}cq?JRr}3v2Bx z^##P4-JRSd+$8}KT*%FF-~4^w%mx<5T%uPowRa>~0}x|hzaugBE<4FQztfE=G9~#+&7(w`wTprWgXZf?=RLx`bTNJ)`jEd22?&+g}L}CIuV1uV=y+4 z+wplU-vISbK&;dgyYvQB*8#B$556a{?8mrRe&>8*k)K)mrY%ZIxS)Ghs=N86?j!L^ z+o9gVUtu%$-_N&0_Vd51PTO*Ec0Sad7`S~8qjS9dLD+V; literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_l1.gds b/testdata/algo/layout_utils_l1.gds new file mode 100644 index 0000000000000000000000000000000000000000..b38fa80d543eeaac1becbcc39081982b51c10eb1 GIT binary patch literal 864 zcma)3yGjE=6g~60J4lo$f*>o{3IR*85fg31fEFo2zQn@P#?Df(vGWHkEUd+ku(3<& zCwT8Xb|=b`4D6oSJu~N?doBoCPf;sfeZyl9JE(9_?%_3!FGj$&aVNw3qsxz%pX2kl z!{?{j1hwnFM?`0U^#HAFDA0xmFz6e87fTI*@+m00$@eQPt1|pw<@RqC_XX&8AftNV z?;6UX_tyHiz+#1nVB7z`k66ztTtar(3BGh6X){DA*2UMP*7IlbAs05 E7XjEqAOHXW literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_l2.gds b/testdata/algo/layout_utils_l2.gds new file mode 100644 index 0000000000000000000000000000000000000000..66e9e3212a4fdf6b4110789c0b4785166f255111 GIT binary patch literal 924 zcmbVKu}T9$5PiG1J6YtE7{o$P@B;#tDuU#qjTq1(h2%>t`~f>l!N$%Xu&}TeKf=b& zGM|u{+uh3=i7qbOy@A=8_ukBcp!F3hr8}Q+*uf@_aFE7unnq_sV56|d_3i%o+tc*$ z^kwhyVKPQ#m)8-|31A#Rs~QTlrUCT31^<(y`at?6DYMS?9sI?@+RO^G^n{PL6n7}M zZQTu>%E}I6(^A-ljZf1(sMAZ;-34_4W24{dQ#Xq1c)n9E zY}o?4y=J}doDW!hc|{TBzT_iHEd5&KFq|CKj%a*w*=~g$WNanv@3%RxtL$(R^34X_ uJy7iW4f?zM1~NFr6MJktEY>l{bIL)3|8Yp&caFSQDYG^suZ`clF_-}l7elN7 literal 0 HcmV?d00001 diff --git a/testdata/algo/layout_utils_l3.gds b/testdata/algo/layout_utils_l3.gds new file mode 100644 index 0000000000000000000000000000000000000000..d5f9d4ce518be5aff90be7ac06f02d4c6281e61a GIT binary patch literal 800 zcma)4u};G<5Pfl+Ybd2nP*GJBA;iFh5GxCUbV35P14GrR>KE_<415K1S2hN|gn=10 zM%X)WXUFuYi0Dc2v;6L!-<<=3F=G^wX}lxF9sq;B-Xk@1by))4I62E^*Dqg>i_`pg z^W*UK0Yy?@M?`}GYzokpK?G_WRzJ#OURBs9K!2LbnQGv_TP`?j<(9kETY9%Z^AiY2 z=fK94tyQ@52E_Y7z|P!r0VPlPfU+08fLMlI&vnVJn=H63Q)-D{nF5Eaulg}{QxhMO zAJA3$rM6yAS?YBEid)BjN^~j$Qt0iC&L_`kCj-${%;C;$Ke literal 0 HcmV?d00001 diff --git a/testdata/ruby/dbCellMapping.rb b/testdata/ruby/dbCellMapping.rb index 3dfb7167a..16e38d824 100644 --- a/testdata/ruby/dbCellMapping.rb +++ b/testdata/ruby/dbCellMapping.rb @@ -28,7 +28,12 @@ def mapping_to_s(ly1, ly2, cm) ly1.each_cell_top_down do |c| s = ly1.cell(c).name if cm.has_mapping?(c) - s += "=>" + ly2.cell(cm.cell_mapping(c)).name + t = cm.cell_mapping(c) + if t == RBA::CellMapping::DropCell + s += "=>(0)" + else + s += "=>" + ly2.cell(t).name + end end r == "" || (r += ";") r += s @@ -50,6 +55,8 @@ class DBCellMapping_TestClass < TestBase assert_equal(mp.has_mapping?(1), false) mp.map(1, 2) assert_equal(mp.cell_mapping(1), 2) + mp.map(1, 3) + assert_equal(mp.cell_mapping(1), 3) ly = RBA::Layout::new @@ -170,6 +177,11 @@ class DBCellMapping_TestClass < TestBase assert_equal(mapping_to_s(ly2, ly1dup, mp), "c0;c2=>c2;c1=>c1;c3=>c3$1") assert_equal(nc.inspect, "[3]") + mp.clear + mp.from_geometry(ly1, top1, ly2, top2) + mp.map(ci2, RBA::CellMapping::DropCell) + assert_equal(mapping_to_s(ly2, ly1, mp), "c0;c2=>(0);c1=>c1;c3") + end end diff --git a/testdata/ruby/dbLayerMapping.rb b/testdata/ruby/dbLayerMapping.rb index c1e353a01..62d70fc96 100644 --- a/testdata/ruby/dbLayerMapping.rb +++ b/testdata/ruby/dbLayerMapping.rb @@ -50,6 +50,8 @@ class DBLayerMapping_TestClass < TestBase assert_equal(mp.has_mapping?(1), false) mp.map(1, 2) assert_equal(mp.layer_mapping(1), 2) + mp.map(1, 3) + assert_equal(mp.layer_mapping(1), 3) ly1 = RBA::Layout::new