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
This commit is contained in:
Matthias Koefferlein
2017-08-30 01:11:38 +02:00
parent 3499c3856a
commit b28317fb69
24 changed files with 746 additions and 60 deletions
+1 -1
View File
@@ -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;
}
/**
+1 -1
View File
@@ -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;
}
/**
+65 -45
View File
@@ -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<db::cell_index_type> &source_cells,
const std::map<db::cell_index_type, db::cell_index_type> &cell_mapping,
std::set<db::cell_index_type> &all_top_level_cells,
std::set<db::cell_index_type> &all_cells_to_copy)
{
std::vector<db::cell_index_type> dropped_cells;
for (std::map<db::cell_index_type, db::cell_index_type>::const_iterator m = cell_mapping.begin (); m != cell_mapping.end (); ++m) {
if (m->second == DropCell) {
dropped_cells.push_back (m->first);
}
}
for (std::vector<db::cell_index_type>::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<db::cell_index_type>::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<unsigned int, unsigned int> &layer_mapping,
std::map<db::cell_index_type, db::cell_index_type> *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<db::cell_index_type> all_top_level_cells;
std::set<db::cell_index_type> all_cells_to_copy;
for (std::vector<db::cell_index_type>::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<db::cell_index_type, db::cell_index_type> new_cell_mapping;
@@ -158,6 +184,11 @@ merge_layouts (db::Layout &target,
}
if (final_cell_mapping) {
for (std::map<db::cell_index_type, db::cell_index_type>::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<db::cell_index_type> &source_cells,
const std::map<db::cell_index_type, db::cell_index_type> &cell_mapping,
const std::map<unsigned int, unsigned int> &layer_mapping)
static void
copy_or_move_shapes (db::Layout &target,
db::Layout &source,
const db::ICplxTrans &trans,
const std::vector<db::cell_index_type> &source_cells,
const std::map<db::cell_index_type, db::cell_index_type> &cell_mapping,
const std::map<unsigned int, unsigned int> &layer_mapping,
bool move)
{
// collect all called cells and all top level cells
std::set<db::cell_index_type> all_top_level_cells;
std::set<db::cell_index_type> all_cells_to_copy;
for (std::vector<db::cell_index_type>::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<unsigned int, unsigned int>::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<db::cell_index_type> &source_cells,
const std::map<db::cell_index_type, db::cell_index_type> &cell_mapping,
const std::map<unsigned int, unsigned int> &layer_mapping)
{
copy_or_move_shapes (target, const_cast<db::Layout &> (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<db::cell_index_type, db::cell_index_type> &cell_mapping,
const std::map<unsigned int, unsigned int> &layer_mapping)
{
// collect all called cells and all top level cells
std::set<db::cell_index_type> all_top_level_cells;
std::set<db::cell_index_type> all_cells_to_copy;
for (std::vector<db::cell_index_type>::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<db::cell_index_type>::const_iterator c = all_cells_to_copy.begin (); c != all_cells_to_copy.end (); ++c) {
for (std::map<unsigned int, unsigned int>::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);
}
// ------------------------------------------------------------
+9
View File
@@ -32,6 +32,7 @@
#include <map>
#include <vector>
#include <limits>
namespace db
{
@@ -110,6 +111,14 @@ private:
std::map <db::Layout::properties_id_type, db::Layout::properties_id_type> 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<db::cell_index_type>::max ();
/**
* @brief Merge one layout into another
*
+38 -12
View File
@@ -23,6 +23,7 @@
#include "gsiDecl.h"
#include "dbCellMapping.h"
#include "dbLayoutUtils.h"
#include "dbLayout.h"
#include <memory>
@@ -30,9 +31,25 @@
namespace gsi
{
static db::cell_index_type drop_cell_const ()
{
return db::DropCell;
}
Class<db::CellMapping> 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<db::CellMapping> 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<db::CellMapping> 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<db::CellMapping> 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<db::CellMapping> 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<db::CellMapping> 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<db::CellMapping> 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<db::CellMapping> 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"
+616
View File
@@ -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<db::cell_index_type, db::cell_index_type> fm;
std::vector<db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> fm;
std::vector<db::cell_index_type> 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<db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> 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<db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> fm;
std::vector<db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> fm;
std::vector<db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> fm;
std::vector<db::cell_index_type> 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<db::cell_index_type> 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<db::cell_index_type> 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<db::cell_index_type> 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<db::cell_index_type, db::cell_index_type> fm;
std::vector<db::cell_index_type> 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");
}
+1
View File
@@ -31,6 +31,7 @@ SOURCES = \
dbLayerMapping.cc \
dbLayout.cc \
dbLayoutDiff.cc \
dbLayoutUtils.cc \
dbLayoutQuery.cc \
dbLibraries.cc \
dbMatrix.cc \
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+13 -1
View File
@@ -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
+2
View File
@@ -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