Provide multi-cell copy/move of shapes (GSI binding)

This commit is contained in:
Matthias Koefferlein 2020-08-29 22:49:38 +02:00
parent 7d3abce201
commit 5280c762e4
4 changed files with 260 additions and 0 deletions

View File

@ -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)
{

View File

@ -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
*/

View File

@ -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", &copy_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", &copy_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"

View File

@ -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