From c05f7c8bd9c1a8eed39340ae51f3ff0482426d1c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 Dec 2023 19:00:43 +0100 Subject: [PATCH] Fixing issue #1549 (error layer handling in RecursiveShapeIterator) --- src/db/db/dbLayout.cc | 4 +- src/db/db/gsiDeclDbCell.cc | 27 +++-- src/db/db/gsiDeclDbLayout.cc | 29 +++--- src/db/db/gsiDeclDbRecursiveShapeIterator.cc | 19 ++++ src/db/db/gsiDeclDbShape.cc | 2 +- testdata/ruby/dbLayoutTests1.rb | 101 +++++++++++++++++++ 6 files changed, 148 insertions(+), 34 deletions(-) diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index c3505b24b1..16bb73473f 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -812,7 +812,7 @@ Layout::delete_cells (const std::set &cells_to_delete) // will disable us saving undo data with reference to them. if (manager () && manager ()->transacting ()) { for (unsigned int i = 0; i < layers (); ++i) { - if (is_valid_layer (i)) { + if (is_valid_layer (i) || is_special_layer (i)) { cref.clear (i); } } @@ -880,7 +880,7 @@ Layout::delete_cell (cell_index_type id) // will disable us saving undo data with reference to them. if (manager () && manager ()->transacting ()) { for (unsigned int i = 0; i < layers (); ++i) { - if (is_valid_layer (i)) { + if (is_valid_layer (i) || is_special_layer (i)) { cref.clear (i); } } diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index 861020f98b..dc93cf15a9 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1369,6 +1369,13 @@ flatten1 (db::Cell *cell, bool prune) flatten (cell, -1, prune); } +static void check_layer (const db::Layout *layout, unsigned int layer) +{ + if (! layout->is_valid_layer (layer) && ! layout->is_special_layer (layer)) { + throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); + } +} + static db::RecursiveShapeIterator begin_shapes_rec (const db::Cell *cell, unsigned int layer) { @@ -1376,9 +1383,7 @@ begin_shapes_rec (const db::Cell *cell, unsigned int layer) if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell is not inside layout"))); } - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); return db::RecursiveShapeIterator (*layout, *cell, layer); } @@ -1389,9 +1394,7 @@ begin_shapes_rec_touching (const db::Cell *cell, unsigned int layer, db::Box reg if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell is not inside layout"))); } - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); return db::RecursiveShapeIterator (*layout, *cell, layer, region, false); } @@ -1402,9 +1405,7 @@ begin_shapes_rec_touching_um (const db::Cell *cell, unsigned int layer, db::DBox if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell is not inside layout"))); } - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); return db::RecursiveShapeIterator (*layout, *cell, layer, db::CplxTrans (layout->dbu ()).inverted () * region, false); } @@ -1415,9 +1416,7 @@ begin_shapes_rec_overlapping (const db::Cell *cell, unsigned int layer, db::Box if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell is not inside layout"))); } - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); return db::RecursiveShapeIterator (*layout, *cell, layer, region, true); } @@ -1428,9 +1427,7 @@ begin_shapes_rec_overlapping_um (const db::Cell *cell, unsigned int layer, db::D if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell is not inside layout"))); } - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); return db::RecursiveShapeIterator (*layout, *cell, layer, db::CplxTrans (layout->dbu ()).inverted () * region, true); } diff --git a/src/db/db/gsiDeclDbLayout.cc b/src/db/db/gsiDeclDbLayout.cc index 2dd2defbf1..2493e3b813 100644 --- a/src/db/db/gsiDeclDbLayout.cc +++ b/src/db/db/gsiDeclDbLayout.cc @@ -681,15 +681,20 @@ write_options2 (db::Layout *layout, const std::string &filename, bool /*gzip*/, write_options1 (layout, filename, options); } -static db::RecursiveShapeIterator +static void check_layer (const db::Layout *layout, unsigned int layer) +{ + if (! layout->is_valid_layer (layer) && ! layout->is_special_layer (layer)) { + throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); + } +} + +static db::RecursiveShapeIterator begin_shapes (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer) { if (! layout->is_valid_layer (layer)) { throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); } - if (! layout->is_valid_cell_index (starting_cell)) { - throw tl::Exception (tl::to_string (tr ("Invalid cell index"))); - } + check_layer (layout, layer); return db::RecursiveShapeIterator (*layout, layout->cell (starting_cell), layer); } @@ -702,9 +707,7 @@ begin_shapes2 (const db::Layout *layout, const db::Cell *cell, unsigned int laye static db::RecursiveShapeIterator begin_shapes_touching (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::Box region) { - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); if (! layout->is_valid_cell_index (starting_cell)) { throw tl::Exception (tl::to_string (tr ("Invalid cell index"))); } @@ -720,9 +723,7 @@ begin_shapes_touching2 (const db::Layout *layout, const db::Cell *cell, unsigned static db::RecursiveShapeIterator begin_shapes_overlapping (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::Box region) { - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); if (! layout->is_valid_cell_index (starting_cell)) { throw tl::Exception (tl::to_string (tr ("Invalid cell index"))); } @@ -738,9 +739,7 @@ begin_shapes_overlapping2 (const db::Layout *layout, const db::Cell *cell, unsig static db::RecursiveShapeIterator begin_shapes_touching_um (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::DBox region) { - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); if (! layout->is_valid_cell_index (starting_cell)) { throw tl::Exception (tl::to_string (tr ("Invalid cell index"))); } @@ -756,9 +755,7 @@ begin_shapes_touching2_um (const db::Layout *layout, const db::Cell *cell, unsig static db::RecursiveShapeIterator begin_shapes_overlapping_um (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::DBox region) { - if (! layout->is_valid_layer (layer)) { - throw tl::Exception (tl::to_string (tr ("Invalid layer index"))); - } + check_layer (layout, layer); if (! layout->is_valid_cell_index (starting_cell)) { throw tl::Exception (tl::to_string (tr ("Invalid cell index"))); } diff --git a/src/db/db/gsiDeclDbRecursiveShapeIterator.cc b/src/db/db/gsiDeclDbRecursiveShapeIterator.cc index e97f17bfe4..8470739032 100644 --- a/src/db/db/gsiDeclDbRecursiveShapeIterator.cc +++ b/src/db/db/gsiDeclDbRecursiveShapeIterator.cc @@ -60,33 +60,52 @@ class IteratorIterator } +static void check_layer (const db::Layout &layout, unsigned int layer) +{ + if (! layout.is_valid_layer (layer) && ! layout.is_special_layer (layer)) { + throw tl::Exception (tl::to_string (tr ("Invalid layer index %d")), int (layer)); + } +} + static db::RecursiveShapeIterator *new_si1 (const db::Layout &layout, const db::Cell &cell, unsigned int layer) { + check_layer (layout, layer); return new db::RecursiveShapeIterator (layout, cell, layer); } static db::RecursiveShapeIterator *new_si2 (const db::Layout &layout, const db::Cell &cell, const std::vector &layers) { + for (auto l = layers.begin (); l != layers.end (); ++l) { + check_layer (layout, *l); + } return new db::RecursiveShapeIterator (layout, cell, layers); } static db::RecursiveShapeIterator *new_si3 (const db::Layout &layout, const db::Cell &cell, unsigned int layer, const db::Box &box, bool overlapping) { + check_layer (layout, layer); return new db::RecursiveShapeIterator (layout, cell, layer, box, overlapping); } static db::RecursiveShapeIterator *new_si3a (const db::Layout &layout, const db::Cell &cell, unsigned int layer, const db::Region ®ion, bool overlapping) { + check_layer (layout, layer); return new db::RecursiveShapeIterator (layout, cell, layer, region, overlapping); } static db::RecursiveShapeIterator *new_si4 (const db::Layout &layout, const db::Cell &cell, const std::vector &layers, const db::Box &box, bool overlapping) { + for (auto l = layers.begin (); l != layers.end (); ++l) { + check_layer (layout, *l); + } return new db::RecursiveShapeIterator (layout, cell, layers, box, overlapping); } static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db::Cell &cell, const std::vector &layers, const db::Region ®ion, bool overlapping) { + for (auto l = layers.begin (); l != layers.end (); ++l) { + check_layer (layout, *l); + } return new db::RecursiveShapeIterator (layout, cell, layers, region, overlapping); } diff --git a/src/db/db/gsiDeclDbShape.cc b/src/db/db/gsiDeclDbShape.cc index d90bb4449b..9c446c3fa3 100644 --- a/src/db/db/gsiDeclDbShape.cc +++ b/src/db/db/gsiDeclDbShape.cc @@ -803,7 +803,7 @@ static void set_shape_layer_index (db::Shape *s, unsigned int layer) throw tl::Exception (tl::to_string (tr ("Shape does not belong to a layout"))); } - if (! layout->is_valid_layer (layer)) { + if (! layout->is_valid_layer (layer) && ! layout->is_special_layer (layer)) { throw tl::Exception (tl::to_string (tr ("Layer index does not point to a valid layer"))); } diff --git a/testdata/ruby/dbLayoutTests1.rb b/testdata/ruby/dbLayoutTests1.rb index a9d084beb2..61a0aa0b70 100644 --- a/testdata/ruby/dbLayoutTests1.rb +++ b/testdata/ruby/dbLayoutTests1.rb @@ -2139,6 +2139,107 @@ def test_issue200 end + # Error layer + def test_issue1549 + + ly = RBA::Layout::new + top = ly.create_cell("TOP") + + ll = ly.layer(1, 0) + el = ly.error_layer + gs = ly.guiding_shape_layer + il = 100 + + assert_equal(true, ly.is_special_layer?(el)) + assert_equal(false, ly.is_valid_layer?(el)) + assert_equal(true, ly.is_special_layer?(gs)) + assert_equal(false, ly.is_valid_layer?(gs)) + assert_equal(false, ly.is_special_layer?(ll)) + assert_equal(true, ly.is_valid_layer?(ll)) + assert_equal(false, ly.is_special_layer?(il)) + assert_equal(false, ly.is_valid_layer?(il)) + + top.shapes(gs).insert(RBA::Box::new(0, 0, 100, 200)) + top.shapes(el).insert(RBA::Box::new(1, 2, 101, 202)) + top.shapes(ll).insert(RBA::Box::new(10, 20, 110, 220)) + + s = RBA::RecursiveShapeIterator::new(ly, top, gs).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (0,0;100,200)", s) + + s = RBA::RecursiveShapeIterator::new(ly, top, [gs]).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (0,0;100,200)", s) + + s = top.begin_shapes_rec(gs).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (0,0;100,200)", s) + + s = top.begin_shapes_rec_touching(gs, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (0,0;100,200)", s) + + s = top.begin_shapes_rec_overlapping(gs, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (0,0;100,200)", s) + + s = RBA::RecursiveShapeIterator::new(ly, top, el).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (1,2;101,202)", s) + + s = RBA::RecursiveShapeIterator::new(ly, top, [el]).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (1,2;101,202)", s) + + s = top.begin_shapes_rec(el).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (1,2;101,202)", s) + + s = top.begin_shapes_rec_touching(el, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (1,2;101,202)", s) + + s = top.begin_shapes_rec_overlapping(el, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (1,2;101,202)", s) + + s = RBA::RecursiveShapeIterator::new(ly, top, ll).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (10,20;110,220)", s) + + s = RBA::RecursiveShapeIterator::new(ly, top, [ll]).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (10,20;110,220)", s) + + s = top.begin_shapes_rec(ll).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (10,20;110,220)", s) + + s = top.begin_shapes_rec_touching(ll, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (10,20;110,220)", s) + + s = top.begin_shapes_rec_overlapping(ll, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal("box (10,20;110,220)", s) + + begin + s = RBA::RecursiveShapeIterator::new(ly, top, il).each.collect { |it| it.shape.to_s }.join("/") + assert_equal(true, false) + rescue => ex + end + + begin + s = RBA::RecursiveShapeIterator::new(ly, top, [il]).each.collect { |it| it.shape.to_s }.join("/") + assert_equal(true, false) + rescue => ex + end + + begin + s = top.begin_shapes_rec(il).each.collect { |it| it.shape.to_s }.join("/") + assert_equal(true, false) + rescue => ex + end + + begin + s = top.begin_shapes_rec_touching(il, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal(true, false) + rescue => ex + end + + begin + s = top.begin_shapes_rec_overlapping(il, RBA::Box::world).each.collect { |it| it.shape.to_s }.join("/") + assert_equal(true, false) + rescue => ex + end + + end + end load("test_epilogue.rb")