mirror of https://github.com/KLayout/klayout.git
Provide multi-cell copy/move of shapes (GSI binding)
This commit is contained in:
parent
7d3abce201
commit
5280c762e4
|
|
@ -269,6 +269,17 @@ void CellMapping::clear ()
|
|||
m_b2a_mapping.clear ();
|
||||
}
|
||||
|
||||
std::vector<db::cell_index_type> CellMapping::source_cells () const
|
||||
{
|
||||
std::vector<db::cell_index_type> s;
|
||||
s.reserve (m_b2a_mapping.size ());
|
||||
for (iterator m = begin (); m != end (); ++m) {
|
||||
s.push_back (m->first);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CellMapping::create_single_mapping (const db::Layout & /*layout_a*/, db::cell_index_type cell_index_a, const db::Layout & /*layout_b*/, db::cell_index_type cell_index_b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -196,6 +196,11 @@ public:
|
|||
return m_b2a_mapping.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the source cells
|
||||
*/
|
||||
std::vector<db::cell_index_type> source_cells () const;
|
||||
|
||||
/**
|
||||
* @brief Access to the mapping table
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
#include "dbEdgePairs.h"
|
||||
#include "dbTexts.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbLayerMapping.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -822,6 +824,56 @@ static void scale_and_snap2 (db::Layout *layout, db::cell_index_type ci, db::Coo
|
|||
scale_and_snap (*layout, layout->cell (ci), g, m, d);
|
||||
}
|
||||
|
||||
static void copy_tree_shapes2 (db::Layout *layout, const db::Layout &source_layout, const db::CellMapping &cm)
|
||||
{
|
||||
if (layout == &source_layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
|
||||
}
|
||||
|
||||
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
|
||||
|
||||
db::LayerMapping lm;
|
||||
lm.create_full (*layout, source_layout);
|
||||
|
||||
db::copy_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
|
||||
}
|
||||
|
||||
static void copy_tree_shapes3 (db::Layout *layout, const db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm)
|
||||
{
|
||||
if (layout == &source_layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
|
||||
}
|
||||
|
||||
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
|
||||
|
||||
db::copy_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
|
||||
}
|
||||
|
||||
static void move_tree_shapes2 (db::Layout *layout, db::Layout &source_layout, const db::CellMapping &cm)
|
||||
{
|
||||
if (layout == &source_layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
|
||||
}
|
||||
|
||||
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
|
||||
|
||||
db::LayerMapping lm;
|
||||
lm.create_full (*layout, source_layout);
|
||||
|
||||
db::move_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
|
||||
}
|
||||
|
||||
static void move_tree_shapes3 (db::Layout *layout, db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm)
|
||||
{
|
||||
if (layout == &source_layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
|
||||
}
|
||||
|
||||
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
|
||||
|
||||
db::move_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
|
||||
}
|
||||
|
||||
Class<db::MetaInfo> decl_LayoutMetaInfo ("db", "LayoutMetaInfo",
|
||||
gsi::constructor ("new", &layout_meta_info_ctor, gsi::arg ("name"), gsi::arg ("value"), gsi::arg ("description", std::string ()),
|
||||
"@brief Creates a layout meta info object\n"
|
||||
|
|
@ -1529,6 +1581,49 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"an index in the range of 0 to layers-1 needs to be a valid layer. These layers can be either valid, "
|
||||
"special or unused. Use \\is_valid_layer? and \\is_special_layer? to test for the first two states.\n"
|
||||
) +
|
||||
gsi::method_ext ("copy_tree_shapes", ©_tree_shapes2, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"),
|
||||
"@brief Copies the shapes for all given mappings in the \\CellMapping object\n"
|
||||
"@param source_layout The layout where to take the shapes from\n"
|
||||
"@param cell_mapping The cell mapping object that determines how cells are identified between source and target layout\n"
|
||||
"\n"
|
||||
"Provide a \\CellMapping object to specify pairs of cells which are mapped from the source layout to this "
|
||||
"layout. When constructing such a cell mapping object for example with \\CellMapping#for_multi_cell_full, use self "
|
||||
"as the target layout. During the cell mapping construction, the cell mapper will usually create a suitable target "
|
||||
"hierarchy already. After having completed the cell mapping, use \\copy_tree_shapes to copy over the shapes from "
|
||||
"the source to the target layout.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("copy_tree_shapes", ©_tree_shapes3, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"), gsi::arg ("layer_mapping"),
|
||||
"@brief Copies the shapes for all given mappings in the \\CellMapping object using the given layer mapping\n"
|
||||
"@param source_layout The layout where to take the shapes from\n"
|
||||
"@param cell_mapping The cell mapping object that determines how cells are identified between source and target layout\n"
|
||||
"@param layer_mapping Specifies which layers are copied from the source layout to the target layout\n"
|
||||
"\n"
|
||||
"Provide a \\CellMapping object to specify pairs of cells which are mapped from the source layout to this "
|
||||
"layout. When constructing such a cell mapping object for example with \\CellMapping#for_multi_cell_full, use self "
|
||||
"as the target layout. During the cell mapping construction, the cell mapper will usually create a suitable target "
|
||||
"hierarchy already. After having completed the cell mapping, use \\copy_tree_shapes to copy over the shapes from "
|
||||
"the source to the target layout.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("move_tree_shapes", &move_tree_shapes2, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"),
|
||||
"@brief Moves the shapes for all given mappings in the \\CellMapping object\n"
|
||||
"\n"
|
||||
"This method acts like the corresponding \\copy_tree_shapes method, but removes the shapes from the source layout "
|
||||
"after they have been copied.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("move_tree_shapes", &move_tree_shapes3, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"), gsi::arg ("layer_mapping"),
|
||||
"@brief Moves the shapes for all given mappings in the \\CellMapping object using the given layer mapping\n"
|
||||
"\n"
|
||||
"This method acts like the corresponding \\copy_tree_shapes method, but removes the shapes from the source layout "
|
||||
"after they have been copied.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("scale_and_snap", &scale_and_snap1, gsi::arg ("cell"), gsi::arg ("grid"), gsi::arg ("mult"), gsi::arg ("div"),
|
||||
"@brief Scales and snaps the layout below a given cell by the given rational factor and snaps to the given grid\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -1994,6 +1994,155 @@ END
|
|||
|
||||
end
|
||||
|
||||
def test_20
|
||||
|
||||
# copy shapes between cell trees starting from multiple 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"))
|
||||
c9 = l.cell(l.add_cell("c9"))
|
||||
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))))
|
||||
c9.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
|
||||
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)")
|
||||
assert_equal(collect(c9.begin_shapes_rec(0), l), "[c1](0,100;1000,1200)")
|
||||
assert_equal(collect(c9.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
|
||||
new_cells = [ c0, c9 ].collect { |c| lt.add_cell(c.name) }
|
||||
( c0t, c9t ) = new_cells.collect { |ci| lt.cell(ci) }
|
||||
org_cells = [ c0, c9 ].collect { |c| c.cell_index }
|
||||
|
||||
cm = RBA::CellMapping::new
|
||||
cm.for_multi_cells(lt, new_cells, l, org_cells)
|
||||
|
||||
lt.copy_tree_shapes(l, cm)
|
||||
assert_equal(collect(c0t.begin_shapes_rec(0), lt), "[c0](0,100;1000,1200)/[c0](0,100;1000,1200)/[c0](100,0;1100,1100)/[c0](-1200,0;-100,1000)/[c0](1200,0;2200,1100)")
|
||||
assert_equal(c0t.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(0), lt), "[c9](0,100;1000,1200)")
|
||||
assert_equal(collect(c0t.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
assert_equal(c0t.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
|
||||
new_cells = [ c0, c9 ].collect { |c| lt.add_cell(c.name) }
|
||||
( c0t, c9t ) = new_cells.collect { |ci| lt.cell(ci) }
|
||||
org_cells = [ c0, c9 ].collect { |c| c.cell_index }
|
||||
|
||||
cm = RBA::CellMapping::new
|
||||
cm.for_multi_cells_full(lt, new_cells, l, org_cells)
|
||||
|
||||
lt.copy_tree_shapes(l, cm)
|
||||
assert_equal(collect(c0t.begin_shapes_rec(0), lt), "[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(c0t.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(0), lt), "[c1](0,100;1000,1200)")
|
||||
assert_equal(collect(c0t.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
assert_equal(c0t.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
lt.layer
|
||||
lt.layer
|
||||
ll = lt.layer
|
||||
|
||||
new_cells = [ c0, c9 ].collect { |c| lt.add_cell(c.name) }
|
||||
( c0t, c9t ) = new_cells.collect { |ci| lt.cell(ci) }
|
||||
org_cells = [ c0, c9 ].collect { |c| c.cell_index }
|
||||
|
||||
cm = RBA::CellMapping::new
|
||||
cm.for_multi_cells_full(lt, new_cells, l, org_cells)
|
||||
|
||||
lm = RBA::LayerMapping::new
|
||||
lm.map(0, ll)
|
||||
|
||||
lt.copy_tree_shapes(l, cm, lm)
|
||||
assert_equal(collect(c0t.begin_shapes_rec(ll), lt), "[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(c0t.begin_shapes_rec(ll).shape.property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(ll), lt), "[c1](0,100;1000,1200)")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
ls = l.dup
|
||||
|
||||
assert_equal(ls.cell(c0.cell_index).name, "c0")
|
||||
assert_equal(ls.cell(c9.cell_index).name, "c9")
|
||||
|
||||
new_cells = [ c0, c9 ].collect { |c| lt.add_cell(c.name) }
|
||||
( c0t, c9t ) = new_cells.collect { |ci| lt.cell(ci) }
|
||||
org_cells = [ c0, c9 ].collect { |c| c.cell_index }
|
||||
|
||||
cm = RBA::CellMapping::new
|
||||
cm.for_multi_cells(lt, new_cells, ls, org_cells)
|
||||
|
||||
lt.move_tree_shapes(ls, cm)
|
||||
|
||||
assert_equal(collect(ls.cell(c0.cell_index).begin_shapes_rec(0), ls), "")
|
||||
assert_equal(collect(ls.cell(c0.cell_index).begin_shapes_rec(1), ls), "")
|
||||
assert_equal(collect(ls.cell(c9.cell_index).begin_shapes_rec(0), ls), "")
|
||||
assert_equal(collect(ls.cell(c9.cell_index).begin_shapes_rec(1), ls), "")
|
||||
|
||||
assert_equal(collect(c0t.begin_shapes_rec(0), lt), "[c0](0,100;1000,1200)/[c0](0,100;1000,1200)/[c0](100,0;1100,1100)/[c0](-1200,0;-100,1000)/[c0](1200,0;2200,1100)")
|
||||
assert_equal(c0t.begin_shapes_rec(0).shape.property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(0), lt), "[c9](0,100;1000,1200)")
|
||||
assert_equal(collect(c0t.begin_shapes_rec(1), l), "[c0](1,101;1001,1201)")
|
||||
assert_equal(c0t.begin_shapes_rec(1).shape.property("p"), 17)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(1), l), "")
|
||||
|
||||
lt = RBA::Layout::new
|
||||
lt.layer
|
||||
lt.layer
|
||||
ll = lt.layer
|
||||
|
||||
ls = l.dup
|
||||
|
||||
assert_equal(ls.cell(c0.cell_index).name, "c0")
|
||||
assert_equal(ls.cell(c9.cell_index).name, "c9")
|
||||
|
||||
new_cells = [ c0, c9 ].collect { |c| lt.add_cell(c.name) }
|
||||
( c0t, c9t ) = new_cells.collect { |ci| lt.cell(ci) }
|
||||
org_cells = [ c0, c9 ].collect { |c| c.cell_index }
|
||||
|
||||
cm = RBA::CellMapping::new
|
||||
cm.for_multi_cells(lt, new_cells, ls, org_cells)
|
||||
|
||||
lm = RBA::LayerMapping::new
|
||||
lm.map(0, ll)
|
||||
|
||||
lt.move_tree_shapes(ls, cm, lm)
|
||||
|
||||
assert_equal(collect(ls.cell(c0.cell_index).begin_shapes_rec(0), ls), "")
|
||||
assert_equal(collect(ls.cell(c0.cell_index).begin_shapes_rec(1), ls), "[c0](1,101;1001,1201)")
|
||||
assert_equal(collect(ls.cell(c9.cell_index).begin_shapes_rec(0), ls), "")
|
||||
assert_equal(collect(ls.cell(c9.cell_index).begin_shapes_rec(1), ls), "")
|
||||
|
||||
assert_equal(collect(c0t.begin_shapes_rec(ll), lt), "[c0](0,100;1000,1200)/[c0](0,100;1000,1200)/[c0](100,0;1100,1100)/[c0](-1200,0;-100,1000)/[c0](1200,0;2200,1100)")
|
||||
assert_equal(c0t.begin_shapes_rec(ll).shape.property("p"), nil)
|
||||
assert_equal(collect(c9t.begin_shapes_rec(ll), lt), "[c9](0,100;1000,1200)")
|
||||
|
||||
end
|
||||
|
||||
# Iterating while flatten
|
||||
def test_issue200
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue