From d762074bc04666ba966b41797e858e698cabfb15 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Aug 2020 23:43:05 +0200 Subject: [PATCH] Some refactoring, Cell#dup for convenience --- src/db/db/dbCell.cc | 311 +++++++++++++++++++++++++++++++++++++ src/db/db/dbCell.h | 80 ++++++++++ src/db/db/gsiDeclDbCell.cc | 304 +++++------------------------------- testdata/ruby/dbLayout.rb | 39 +++++ 4 files changed, 466 insertions(+), 268 deletions(-) diff --git a/src/db/db/dbCell.cc b/src/db/db/dbCell.cc index 1c8968b28..0b1522e82 100644 --- a/src/db/db/dbCell.cc +++ b/src/db/db/dbCell.cc @@ -26,6 +26,9 @@ #include "dbManager.h" #include "dbBox.h" #include "dbPCellVariant.h" +#include "dbLayoutUtils.h" +#include "dbLayerMapping.h" +#include "dbCellMapping.h" #include @@ -726,5 +729,313 @@ Cell::set_name (const std::string &name) layout ()->rename_cell (cell_index (), name.c_str ()); } +void +Cell::copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_mapping) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + const db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + if (target_layout != source_layout) { + db::PropertyMapper pm (*target_layout, *source_layout); + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { + shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm); + } + } else { + for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { + shapes (lm->second).insert (source_cell.shapes (lm->first)); + } + } +} + +void +Cell::copy_shapes (const db::Cell &source_cell) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); + } + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + + if (target_layout != source_cell.layout ()) { + if (! source_cell.layout ()) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + db::LayerMapping lm; + lm.create_full (*target_layout, *source_cell.layout ()); + this->copy_shapes (source_cell, lm); + } else { + for (db::Layout::layer_iterator l = target_layout->begin_layers (); l != target_layout->end_layers (); ++l) { + shapes ((*l).first).insert (source_cell.shapes ((*l).first)); + } + } +} + +void +Cell::copy_instances (const db::Cell &source_cell) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot copy instances within the same cell"))); + } + if (layout () != source_cell.layout ()) { + throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout"))); + } + + for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) { + insert (*i); + } +} + +std::vector +Cell::copy_tree (const db::Cell &source_cell) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + const db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + + db::CellMapping cm; + std::vector new_cells = cm.create_single_mapping_full (*target_layout, cell_index (), *source_layout, source_cell.cell_index ()); + + db::LayerMapping lm; + lm.create_full (*target_layout, *source_cell.layout ()); + + std::vector source_cells; + source_cells.push_back (source_cell.cell_index ()); + db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); + + return new_cells; +} + +void +Cell::copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + const db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + + db::LayerMapping lm; + lm.create_full (*target_layout, *source_cell.layout ()); + + std::vector source_cells; + source_cells.push_back (source_cell.cell_index ()); + db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); +} + +void +Cell::copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + const db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + + std::vector source_cells; + source_cells.push_back (source_cell.cell_index ()); + db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); +} + +void +Cell::move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + if (target_layout != source_layout) { + db::PropertyMapper pm (*target_layout, *source_layout); + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { + shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm); + source_cell.shapes (lm->first).clear (); + } + } else { + for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { + shapes (lm->second).insert (source_cell.shapes (lm->first)); + source_cell.shapes (lm->first).clear (); + } + } +} + +void +Cell::move_shapes (db::Cell &source_cell) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); + } + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + + if (target_layout != source_cell.layout ()) { + if (! source_cell.layout ()) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + db::LayerMapping lm; + lm.create_full (*target_layout, *source_cell.layout ()); + move_shapes (source_cell, lm); + } else { + for (db::Layout::layer_iterator l = target_layout->begin_layers (); l != target_layout->end_layers (); ++l) { + shapes ((*l).first).insert (source_cell.shapes ((*l).first)); + source_cell.shapes ((*l).first).clear (); + } + } +} + +void +Cell::move_instances (db::Cell &source_cell) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot move instances within the same cell"))); + } + if (layout () != source_cell.layout ()) { + throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout"))); + } + + for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) { + insert (*i); + } + + source_cell.clear_insts (); +} + +std::vector +Cell::move_tree (db::Cell &source_cell) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + db::PropertyMapper pm (*target_layout, *source_layout); + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + + db::CellMapping cm; + std::vector new_cells = cm.create_single_mapping_full (*target_layout, cell_index (), *source_layout, source_cell.cell_index ()); + + db::LayerMapping lm; + lm.create_full (*target_layout, *source_cell.layout ()); + + std::vector source_cells; + source_cells.push_back (source_cell.cell_index ()); + db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); + + source_layout->prune_subcells (source_cell.cell_index ()); + + return new_cells; +} + +void +Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + db::PropertyMapper pm (*target_layout, *source_layout); + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + + db::LayerMapping lm; + lm.create_full (*target_layout, *source_cell.layout ()); + + std::vector source_cells; + source_cells.push_back (source_cell.cell_index ()); + db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); +} + +void +Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm) +{ + if (this == &source_cell) { + throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); + } + + db::Layout *target_layout = layout (); + if (! target_layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); + } + db::Layout *source_layout = source_cell.layout (); + if (! source_layout) { + throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); + } + + db::PropertyMapper pm (*target_layout, *source_layout); + db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); + + std::vector source_cells; + source_cells.push_back (source_cell.cell_index ()); + db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); +} + } diff --git a/src/db/db/dbCell.h b/src/db/db/dbCell.h index 56e5e6b9a..83b9ff2cc 100644 --- a/src/db/db/dbCell.h +++ b/src/db/db/dbCell.h @@ -55,6 +55,8 @@ template class generic_repository; class Layout; class Library; class ImportLayerMapping; +class CellMapping; +class LayerMapping; /** * @brief The cell object @@ -937,6 +939,84 @@ public: return mp_layout; } + /** + * @brief Copies the shapes from the source cell's tree to this cell + * + * This variant uses the given cell mapping and layer mapping. + */ + void copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm); + + /** + * @brief Copies the shapes from the source cell's tree to this cell + * + * This variant uses the given cell mapping and layer mapping. + */ + void copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm); + + /** + * @brief Copies instances and shapes from the source cell to this cell + * + * If the source and target layout are different ones, the whole cell tree of the source cell + * will be copied. + * This will create new cells in the target layout to accomodate the source cell tree. + * Returns an array with the freshly created cells which acommodate the cell tree. + */ + std::vector copy_tree (const db::Cell &source_cell); + + /** + * @brief Copies the instances from the source to this cell. + */ + void copy_instances (const db::Cell &source_cell); + + /** + * @brief Copies all shapes from the source cell to this cell + */ + void copy_shapes (const db::Cell &source_cell); + + /** + * @brief Copies all shapes from the source cell to this cell using the given layer mapping + */ + void copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_mapping); + + /** + * @brief Moves the shapes from the source cell's tree to this cell + * + * This variant uses the given cell mapping and layer mapping. + */ + void move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm); + + /** + * @brief Moves the shapes from the source cell's tree to this cell + * + * This variant uses the given cell mapping and layer mapping. + */ + void move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm); + + /** + * @brief Moves instances and shapes from the source cell to this cell + * + * If the source and target layout are different ones, the whole cell tree of the source cell + * will be copied. + * This will create new cells in the target layout to accomodate the source cell tree. + * Returns an array with the freshly created cells which acommodate the cell tree. + */ + std::vector move_tree (db::Cell &source_cell); + + /** + * @brief Moves the instances from the source to this cell. + */ + void move_instances (db::Cell &source_cell); + + /** + * @brief Moves all shapes from the source cell to this cell + */ + void move_shapes (db::Cell &source_cell); + + /** + * @brief Moves all shapes from the source cell to this cell using the given layer mapping + */ + void move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping); + protected: /** * @brief Standard constructor: create an empty cell object diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index e41ef5972..1ca13c811 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1206,298 +1206,42 @@ begin_shapes_rec_overlapping_um (const db::Cell *cell, unsigned int layer, db::D static void copy_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::LayerMapping &layer_mapping) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - const db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - if (target_layout != source_layout) { - db::PropertyMapper pm (*target_layout, *source_layout); - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { - cell->shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm); - } - } else { - for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { - cell->shapes (lm->second).insert (source_cell.shapes (lm->first)); - } - } + cell->copy_shapes (source_cell, layer_mapping); } static void copy_shapes1 (db::Cell *cell, const db::Cell &source_cell) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); - } - db::Layout *layout = cell->layout (); - if (! layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - - if (layout != source_cell.layout ()) { - if (! source_cell.layout ()) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - db::LayerMapping lm; - lm.create_full (*layout, *source_cell.layout ()); - copy_shapes2 (cell, source_cell, lm); - } else { - for (db::Layout::layer_iterator l = layout->begin_layers (); l != layout->end_layers (); ++l) { - cell->shapes ((*l).first).insert (source_cell.shapes ((*l).first)); - } - } -} - -static void copy_instances (db::Cell *cell, const db::Cell &source_cell) -{ - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot copy instances within the same cell"))); - } - if (cell->layout () != source_cell.layout ()) { - throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout"))); - } - - for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) { - cell->insert (*i); - } -} - -static std::vector copy_tree (db::Cell *cell, const db::Cell &source_cell) -{ - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - const db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - - db::CellMapping cm; - std::vector new_cells = cm.create_single_mapping_full (*target_layout, cell->cell_index (), *source_layout, source_cell.cell_index ()); - - db::LayerMapping lm; - lm.create_full (*target_layout, *source_cell.layout ()); - - std::vector source_cells; - source_cells.push_back (source_cell.cell_index ()); - db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); - - return new_cells; + cell->copy_shapes (source_cell); } static void copy_tree_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::CellMapping &cm) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - const db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - - db::LayerMapping lm; - lm.create_full (*target_layout, *source_cell.layout ()); - - std::vector source_cells; - source_cells.push_back (source_cell.cell_index ()); - db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); + cell->copy_tree_shapes (source_cell, cm); } static void copy_tree_shapes3 (db::Cell *cell, const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - const db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - - std::vector source_cells; - source_cells.push_back (source_cell.cell_index ()); - db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); + cell->copy_tree_shapes (source_cell, cm, lm); } static void move_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::LayerMapping &layer_mapping) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - if (target_layout != source_layout) { - db::PropertyMapper pm (*target_layout, *source_layout); - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { - cell->shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm); - source_cell.shapes (lm->first).clear (); - } - } else { - for (std::map::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) { - cell->shapes (lm->second).insert (source_cell.shapes (lm->first)); - source_cell.shapes (lm->first).clear (); - } - } + cell->move_shapes (source_cell, layer_mapping); } static void move_shapes1 (db::Cell *cell, db::Cell &source_cell) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); - } - db::Layout *layout = cell->layout (); - if (! layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - - if (layout != source_cell.layout ()) { - if (! source_cell.layout ()) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - db::LayerMapping lm; - lm.create_full (*layout, *source_cell.layout ()); - move_shapes2 (cell, source_cell, lm); - } else { - for (db::Layout::layer_iterator l = layout->begin_layers (); l != layout->end_layers (); ++l) { - cell->shapes ((*l).first).insert (source_cell.shapes ((*l).first)); - source_cell.shapes ((*l).first).clear (); - } - } -} - -static void move_instances (db::Cell *cell, db::Cell &source_cell) -{ - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot move instances within the same cell"))); - } - if (cell->layout () != source_cell.layout ()) { - throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout"))); - } - - for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) { - cell->insert (*i); - } - - source_cell.clear_insts (); -} - -static std::vector move_tree (db::Cell *cell, db::Cell &source_cell) -{ - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - db::PropertyMapper pm (*target_layout, *source_layout); - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - - db::CellMapping cm; - std::vector new_cells = cm.create_single_mapping_full (*target_layout, cell->cell_index (), *source_layout, source_cell.cell_index ()); - - db::LayerMapping lm; - lm.create_full (*target_layout, *source_cell.layout ()); - - std::vector source_cells; - source_cells.push_back (source_cell.cell_index ()); - db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); - - source_layout->prune_subcells (source_cell.cell_index ()); - - return new_cells; + cell->move_shapes (source_cell); } static void move_tree_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::CellMapping &cm) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - db::PropertyMapper pm (*target_layout, *source_layout); - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - - db::LayerMapping lm; - lm.create_full (*target_layout, *source_cell.layout ()); - - std::vector source_cells; - source_cells.push_back (source_cell.cell_index ()); - db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); + cell->move_tree_shapes (source_cell, cm); } static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm) { - if (cell == &source_cell) { - throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell"))); - } - - db::Layout *target_layout = cell->layout (); - if (! target_layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout"))); - } - db::Layout *source_layout = source_cell.layout (); - if (! source_layout) { - throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout"))); - } - - db::PropertyMapper pm (*target_layout, *source_layout); - db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ()); - - std::vector source_cells; - source_cells.push_back (source_cell.cell_index ()); - db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ()); + cell->move_tree_shapes (source_cell, cm, lm); } static void @@ -1686,6 +1430,21 @@ static const db::Shapes *shapes_of_cell_const (const db::Cell *cell, unsigned in return &cell->shapes (layer); } +static db::Cell *dup_cell (const db::Cell *cell) +{ + if (! cell->layout ()) { + throw tl::Exception (tl::to_string (tr ("Cannot create a copy of a cell which is not part of a layout"))); + } + + db::Layout *layout = const_cast (cell->layout ()); + db::Cell *new_cell = &layout->cell (layout->add_cell (layout->cell_name (cell->cell_index ()))); + + new_cell->copy_shapes (*cell); + new_cell->copy_instances (*cell); + + return new_cell; +} + Class decl_Cell ("db", "Cell", gsi::method ("name", &db::Cell::get_basic_name, "@brief Gets the cell's name\n" @@ -1759,6 +1518,15 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been introduced in version 0.23.\n" ) + + gsi::method_ext ("dup", &dup_cell, + "@brief Creates a copy of the cell\n" + "\n" + "This method will create a copy of the cell. The new cell will be member of the same layout the original cell " + "was member of. The copy will inherit all shapes and instances, but get " + "a different cell_index and a modified name as duplicate cell names are not allowed in the same layout.\n" + "\n" + "This method has been introduced in version 0.27.\n" + ) + gsi::method ("shapes", (db::Cell::shapes_type &(db::Cell::*) (unsigned int)) &db::Cell::shapes, gsi::arg ("layer_index"), "@brief Returns the shapes list of the given layer\n" "\n" @@ -2092,7 +1860,7 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been added in version 0.23.\n" ) + - gsi::method_ext ("copy_instances", ©_instances, gsi::arg ("source_cell"), + gsi::method ("copy_instances", &db::Cell::copy_instances, gsi::arg ("source_cell"), "@brief Copies the instances of child cells in the source cell to this cell\n" "@param source_cell The cell where the instances are copied from\n" "The source cell must reside in the same layout than this cell. The instances of " @@ -2106,7 +1874,7 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been added in version 0.23.\n" ) + - gsi::method_ext ("copy_tree", ©_tree, gsi::arg ("source_cell"), + gsi::method ("copy_tree", &db::Cell::copy_tree, gsi::arg ("source_cell"), "@brief Copies the cell tree of the given cell into this cell\n" "@param source_cell The cell from where to copy the cell tree\n" "@return A list of indexes of newly created cells\n" @@ -2196,7 +1964,7 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been added in version 0.23.\n" ) + - gsi::method_ext ("move_instances", &move_instances, gsi::arg ("source_cell"), + gsi::method ("move_instances", &db::Cell::move_instances, gsi::arg ("source_cell"), "@brief Moves the instances of child cells in the source cell to this cell\n" "@param source_cell The cell where the instances are moved from\n" "The source cell must reside in the same layout than this cell. The instances of " @@ -2210,7 +1978,7 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been added in version 0.23.\n" ) + - gsi::method_ext ("move_tree", &move_tree, gsi::arg ("source_cell"), + gsi::method ("move_tree", &db::Cell::move_tree, gsi::arg ("source_cell"), "@brief Moves the cell tree of the given cell into this cell\n" "@param source_cell The cell from where to move the cell tree\n" "@return A list of indexes of newly created cells\n" diff --git a/testdata/ruby/dbLayout.rb b/testdata/ruby/dbLayout.rb index ecb2efff1..e5ff45791 100644 --- a/testdata/ruby/dbLayout.rb +++ b/testdata/ruby/dbLayout.rb @@ -2143,6 +2143,45 @@ END end + def test_21 + + # dup cells + + l = RBA::Layout.new + l.insert_layer_at(0, RBA::LayerInfo.new(1, 0)) + l.insert_layer_at(1, RBA::LayerInfo.new(2, 0)) + c0 = l.cell(l.add_cell("c0")) + c1 = l.cell(l.add_cell("c1")) + c2 = l.cell(l.add_cell("c2")) + c3 = l.cell(l.add_cell("c3")) + + b = RBA::Box.new(0, 100, 1000, 1200) + c0.shapes(0).insert(b) + c1.shapes(0).insert(b) + c2.shapes(0).insert(b) + c3.shapes(0).insert(b) + b = RBA::Box.new(1, 101, 1001, 1201) + s = c0.shapes(1).insert(b) + s.set_property("p", 17) + + tt = RBA::Trans.new + s = c0.insert(RBA::CellInstArray.new(c1.cell_index, tt)) + s.set_property("p", 18) + c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100)))) + c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1))) + c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0)))) + + assert_equal(collect(c0.begin_shapes_rec(0), l), "[c0](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)/[c1](0,100;1000,1200)") + assert_equal(collect(c0.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)") + + c9 = c0.dup + + assert_equal(c9.name, "c0$1") + assert_equal(collect(c9.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)/[c1](0,100;1000,1200)") + assert_equal(collect(c9.begin_shapes_rec(1), l), "[c0$1](1,101;1001,1201)") + + end + # Iterating while flatten def test_issue200