Skip to content

Commit

Permalink
Merge pull request #1849 from KLayout/feature/issue-1836
Browse files Browse the repository at this point in the history
Implemented solution for issue #1836 (Allow the usage of Cell.shapes(…
  • Loading branch information
klayoutmatthias authored Sep 8, 2024
2 parents d70389c + bf965a7 commit 53b7c98
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 4 deletions.
68 changes: 66 additions & 2 deletions src/db/db/gsiDeclDbCell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,39 @@ read_simple (db::Cell *cell, const std::string &path)
return read_options (cell, path, db::LoadLayoutOptions ());
}

static db::Shapes &shapes_with_layer_info (db::Cell *cell, const db::LayerProperties &info)
{
if (! cell->layout ()) {
throw tl::Exception (tl::to_string (tr ("Cell is not associated with a layout")));
}

unsigned int li = cell->layout ()->get_layer (info);
return cell->shapes (li);
}

static const db::Shapes &shapes_with_layer_info_const (const db::Cell *cell, const db::LayerProperties &info)
{
if (! cell->layout ()) {
throw tl::Exception (tl::to_string (tr ("Cell is not associated with a layout")));
}

int li = cell->layout ()->get_layer_maybe (info);
if (li < 0) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("%s is not a valid layer within the layout of the cell")), info.to_string ()));
}

return cell->shapes ((unsigned int) li);
}

static void clear_layer_with_info (db::Cell *cell, const db::LayerProperties &info)
{
if (cell->layout ()) {
int layer = cell->layout ()->get_layer_maybe (info);
if (layer >= 0) {
cell->clear ((unsigned int) layer);
}
}
}

static db::Point default_origin;

Expand Down Expand Up @@ -1992,22 +2025,46 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"This method gives access to the shapes list on a certain layer.\n"
"If the layer does not exist yet, it is created.\n"
"\n"
"@param index The layer index of the shapes list to retrieve\n"
"@param layer_index The layer index of the shapes list to retrieve\n"
"\n"
"@return A reference to the shapes list\n"
) +
gsi::method_ext ("shapes", shapes_with_layer_info, gsi::arg ("layer"),
"@brief Returns the shapes list of the given layer\n"
"\n"
"This version takes a \\LayerInfo object and will look up the layer index. If no layer exists "
"with these attributes, it will be created.\n"
"\n"
"@param layer The layer attributes\n"
"\n"
"@return A reference to the shapes list\n"
"\n"
"This variant has been introduced in version 0.29.7.\n"
) +
gsi::method_ext ("shapes", &shapes_of_cell_const, gsi::arg ("layer_index"),
"@brief Returns the shapes list of the given layer (const version)\n"
"\n"
"This method gives access to the shapes list on a certain layer. This is the const version - only const (reading) methods "
"can be called on the returned object.\n"
"\n"
"@param index The layer index of the shapes list to retrieve\n"
"@param layer_index The layer index of the shapes list to retrieve\n"
"\n"
"@return A reference to the shapes list\n"
"\n"
"This variant has been introduced in version 0.26.4.\n"
) +
gsi::method_ext ("shapes", shapes_with_layer_info_const, gsi::arg ("layer"),
"@brief Returns the shapes list of the given layer (const version)\n"
"\n"
"This version takes a \\LayerInfo object and will look up the layer index. An error is raised if "
"no layer with these attributes exists.\n"
"\n"
"@param layer The layer attributes\n"
"\n"
"@return A reference to the shapes list\n"
"\n"
"This variant has been introduced in version 0.29.7.\n"
) +
gsi::method ("clear_shapes", &db::Cell::clear_shapes,
"@brief Clears all shapes in the cell\n"
) +
Expand Down Expand Up @@ -2082,6 +2139,13 @@ Class<db::Cell> decl_Cell ("db", "Cell",
gsi::method ("clear", &db::Cell::clear, gsi::arg ("layer_index"),
"@brief Clears the shapes on the given layer\n"
) +
gsi::method_ext ("clear", &clear_layer_with_info, gsi::arg ("layer"),
"@brief Clears the shapes on the given layer\n"
"\n"
"This version takes a \\LayerInfo object for the layer. If no such layer exists, this method does nothing.\n"
"\n"
"This variant has been introduced in version 0.29.7.\n"
) +
gsi::method_ext ("clear", &clear_all,
"@brief Clears the cell (deletes shapes and instances)\n"
"This method has been introduced in version 0.23.\n"
Expand Down
58 changes: 56 additions & 2 deletions src/db/db/gsiDeclDbLayout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,30 @@ void break_polygons1 (db::Layout *layout, size_t max_vertex_count, double max_ar
db::break_polygons (*layout, max_vertex_count, max_area_ratio);
}

void delete_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
{
int li = layout->get_layer_maybe (info);
if (li >= 0) {
layout->delete_layer ((unsigned int) li);
}
}

void clear_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
{
int li = layout->get_layer_maybe (info);
if (li >= 0) {
layout->clear_layer ((unsigned int) li);
}
}

void clear_layer_from_info_with_flags (db::Layout *layout, const db::LayerProperties &info, unsigned int flags)
{
int li = layout->get_layer_maybe (info);
if (li >= 0) {
layout->clear_layer ((unsigned int) li, flags);
}
}

Class<db::Layout> decl_Layout ("db", "Layout",
gsi::constructor ("new", &layout_ctor_with_manager, gsi::arg ("manager"),
"@brief Creates a layout object attached to a manager\n"
Expand Down Expand Up @@ -1963,18 +1987,38 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"This method was introduced in version 0.19.\n"
"\n"
"@param layer_index The index of the layer to delete.\n"
"@param layer_index The index of the layer to clear.\n"
) +
gsi::method_ext ("clear_layer", &clear_layer_from_info, gsi::arg ("layer"),
"@brief Clears a layer\n"
"\n"
"This variant takes a \\LayerInfo object to address the layer.\n"
"It does nothing if no layer with these attributes exists.\n"
"\n"
"This variant was introduced in version 0.26.7.\n"
"\n"
"@param layer The attributes of the layer to clear.\n"
) +
gsi::method ("clear_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int)> (&db::Layout::clear_layer), gsi::arg ("layer_index"), gsi::arg ("flags"),
"@brief Clears a layer (given shape types only)\n"
"\n"
"Clears the layer: removes all shapes for the given shape types.\n"
"\n"
"This method was introduced in version 0.28.9.\n"
"\n"
"@param layer_index The index of the layer to delete.\n"
"@param layer_index The index of the layer to clear.\n"
"@param flags The type selector for the shapes to delete (see \\Shapes class, S... constants).\n"
) +
gsi::method_ext ("clear_layer", &clear_layer_from_info_with_flags, gsi::arg ("layer"), gsi::arg ("flags"),
"@brief Clears a layer (given shape types only)\n"
"\n"
"This variant takes a \\LayerInfo object to address the layer.\n"
"It does nothing if no layer with these attributes exists.\n"
"\n"
"This variant was introduced in version 0.26.7.\n"
"\n"
"@param layer The attributes of the layer to clear.\n"
) +
gsi::method ("delete_layer", &db::Layout::delete_layer, gsi::arg ("layer_index"),
"@brief Deletes a layer\n"
"\n"
Expand All @@ -1983,6 +2027,16 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"@param layer_index The index of the layer to delete.\n"
) +
gsi::method_ext ("delete_layer", &delete_layer_from_info, gsi::arg ("layer"),
"@brief Deletes a layer\n"
"\n"
"This variant takes a \\LayerInfo object to address the layer.\n"
"It does nothing if no layer with these attributes exists.\n"
"\n"
"This variant was introduced in version 0.26.7.\n"
"\n"
"@param layer The attributes of the layer to delete.\n"
) +
gsi::method_ext ("layer_indexes|#layer_indices", &layer_indexes,
"@brief Gets a list of valid layer's indices\n"
"This method returns an array with layer indices representing valid layers.\n"
Expand Down
26 changes: 26 additions & 0 deletions testdata/ruby/dbCellTests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,32 @@ def test_2

end

# methods with LayerInfo instead layer index
def test_3

ly = RBA::Layout::new
top = ly.create_cell("TOP")

l1 = ly.layer(1, 0)
top.shapes(RBA::LayerInfo::new(1, 0)).insert(RBA::Box::new(0, 0, 100, 200))

assert_equal(top.shapes(l1).size, 1)

# unknown layers are ignored in clear
top.clear(RBA::LayerInfo::new(2, 0))
assert_equal(top.shapes(l1).size, 1)

# clear with LayerInfo
top.clear(RBA::LayerInfo::new(1, 0))
assert_equal(top.shapes(l1).size, 0)

# layer is created if not there
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0) ])
top.shapes(RBA::LayerInfo::new(2, 0)).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0), RBA::LayerInfo::new(2, 0) ])

end

end

load("test_epilogue.rb")
37 changes: 37 additions & 0 deletions testdata/ruby/dbLayoutTests1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2144,6 +2144,43 @@ def shapes2str(shapes)

end

# Methods taking LayoutInfo instead of layer index
def test_26

ly = RBA::Layout::new
top = ly.create_cell("TOP")
l1 = ly.layer(1, 0)

# ignored
ly.clear_layer(RBA::LayerInfo::new(2, 0))

top.shapes(l1).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(top.shapes(l1).size, 1)

ly.clear_layer(RBA::LayerInfo::new(1, 0))
assert_equal(top.shapes(l1).size, 0)

top.shapes(l1).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(top.shapes(l1).size, 1)

ly.clear_layer(RBA::LayerInfo::new(1, 0), RBA::Shapes::SPolygons)
assert_equal(top.shapes(l1).size, 1)

ly.clear_layer(RBA::LayerInfo::new(1, 0), RBA::Shapes::SBoxes)
assert_equal(top.shapes(l1).size, 0)

assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0) ])

# ignored
ly.delete_layer(RBA::LayerInfo::new(2, 0))
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0) ])

ly.delete_layer(RBA::LayerInfo::new(1, 0))
assert_equal(ly.layer_infos, [ ])

end


# Iterating while flatten
def test_issue200

Expand Down

0 comments on commit 53b7c98

Please sign in to comment.