/* KLayout Layout Viewer Copyright (C) 2006-2021 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dbHierarchyBuilder.h" #include "dbReader.h" #include "dbTestSupport.h" #include "dbRegion.h" #include "tlUnitTest.h" #include "tlStream.h" TEST(1) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::HierarchyBuilder builder (&target); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1); iter.push (&builder); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au1.gds"); } TEST(1_WithEmptyLayer) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::cell_index_type top_cell_index = *ly.begin_top_down (); db::Layout target; db::HierarchyBuilder builder (&target); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), std::set ()); iter.push (&builder); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1); iter.push (&builder); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au1.gds"); } TEST(2_WithoutClip) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::HierarchyBuilder builder (&target); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, db::Box (5000, -2000, 18500, 6000)); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au2a.gds"); } TEST(2_WithClip) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::ClippingHierarchyBuilderShapeReceiver clip; db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, db::Box (5000, -2000, 18500, 6000)); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au2b.gds"); } TEST(2_WithClipAndSimplification) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::ReducingHierarchyBuilderShapeReceiver red(0, 1.2, 4); db::ClippingHierarchyBuilderShapeReceiver clip(&red); db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, db::Box (5000, -2000, 18500, 6000)); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au2c.gds"); } TEST(2_WithClipAndRefGeneration) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::PolygonReferenceHierarchyBuilderShapeReceiver ref(&target); db::ClippingHierarchyBuilderShapeReceiver clip(&ref); db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, db::Box (5000, -2000, 18500, 6000)); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au2d.gds"); } TEST(2_WithEmptyResult) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::PolygonReferenceHierarchyBuilderShapeReceiver ref(&target); db::ClippingHierarchyBuilderShapeReceiver clip(&ref); db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, db::Box (5000, 10000, 18500, 15000)); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au2e.gds"); } TEST(2_WithClipAndSimplificationAndEmptyLayer) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::ReducingHierarchyBuilderShapeReceiver red(0, 1.2, 4); db::ClippingHierarchyBuilderShapeReceiver clip(&red); db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); db::Box clip_box (5000, -2000, 18500, 6000); builder.set_target_layer (target.insert_layer (db::LayerProperties (100, 0))); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), std::set (), clip_box); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, clip_box); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au2f.gds"); } TEST(3_ComplexRegionWithClip) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l2.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::ClippingHierarchyBuilderShapeReceiver clip; db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::Region reg; reg.insert (db::Box (5000, 13000, 18500, 20000)); reg.insert (db::Box (11000, 20000, 18500, 36000)); reg.merge (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, reg); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au3a.gds"); } TEST(4_ComplexRegionAndLayoutWithClip) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l3.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::ClippingHierarchyBuilderShapeReceiver clip; db::HierarchyBuilder builder (&target, db::ICplxTrans (), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::Region reg; reg.insert (db::Box (5000, 13000, 18500, 20000)); reg.insert (db::Box (11000, 20000, 18500, 36000)); reg.merge (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, reg); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au4a.gds"); } TEST(5_CompareRecursiveShapeIterators) { db::Layout ly; db::cell_index_type ci = ly.add_cell ("TOP"); db::cell_index_type ci1 = ly.add_cell ("TOPA"); db::Layout ly2; db::cell_index_type ci2 = ly2.add_cell ("TOP"); { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0); db::RecursiveShapeIterator iter2 (ly2, ly2.cell (ci2), 0); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci1), 0); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 1); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2), 0); } { std::vector ll1; ll1.push_back (100); ll1.push_back (101); db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), ll1); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 1); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2), 0); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0); iter1.max_depth (1); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0); iter2.max_depth (1); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2), 0); iter2.max_depth (2); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2), 0); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 1, db::Box (0, 1000, 2000, 3000)); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { std::vector ll1; ll1.push_back (100); ll1.push_back (101); db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), ll1, db::Box (0, 1000, 2000, 3000)); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3001)); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::Region r1; r1.insert (db::Box (0, 1000, 2000, 3000)); db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, r1); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2), 0); } { db::Region r1; r1.insert (db::Box (0, 1000, 2000, 3000)); r1.insert (db::Box (0, 4000, 2000, 6000)); db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, r1); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0, db::Box (0, 1000, 2000, 3000)); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } { db::Region r1; r1.insert (db::Box (0, 1000, 2000, 3000)); r1.insert (db::Box (0, 4000, 2000, 6000)); db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, r1); db::Region r2; r2.insert (db::Box (0, 1000, 2000, 3000)); r2.insert (db::Box (0, 4000, 2000, 6000)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0, r2); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2), 0); } { db::Region r1; r1.insert (db::Box (0, 1000, 2000, 3000)); r1.insert (db::Box (0, 4000, 2000, 6000)); db::RecursiveShapeIterator iter1 (ly, ly.cell (ci), 0, r1); db::Region r2; r2.insert (db::Box (0, 1000, 2000, 3000)); r2.insert (db::Box (0, 4000, 2000, 6001)); db::RecursiveShapeIterator iter2 (ly, ly.cell (ci), 0, r2); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != 0, true); EXPECT_EQ (db::compare_iterators_with_respect_to_target_hierarchy (iter1, iter2) != db::compare_iterators_with_respect_to_target_hierarchy (iter2, iter1), true); } } TEST(6_DisjunctLayersPerHierarchyBranch) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l4.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::HierarchyBuilder builder (&target); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1); iter.push (&builder); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au_l4.gds"); } TEST(7_DetachFromOriginalLayout) { // using OASIS means we create a lot of references to array // and shape repo - we check here whether these references get // translated or resolved in the hierarchy builder. std::unique_ptr ly (new db::Layout (false)); { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l5.oas.gz"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (*ly); } db::Layout target; db::HierarchyBuilder builder (&target); for (db::Layout::layer_iterator li = ly->begin_layers (); li != ly->end_layers (); ++li) { unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly->begin_top_down (); db::RecursiveShapeIterator iter (*ly, ly->cell (top_cell_index), li1); iter.push (&builder); } // make sure there is no connection to original layout ly.reset (0); CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au_l5.gds"); } TEST(8a_SimpleWithTrans) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::HierarchyBuilder builder (&target, db::ICplxTrans (2.0, 45.0, false, db::Vector ())); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1); iter.push (&builder); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au8a.gds"); } TEST(8b_ComplexRegionWithTransformation) { db::Layout ly; { std::string fn (tl::testdata ()); fn += "/algo/hierarchy_builder_l2.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); } db::Layout target; db::ClippingHierarchyBuilderShapeReceiver clip; db::HierarchyBuilder builder (&target, db::ICplxTrans (2.0, 45.0, false, db::Vector ()), &clip); db::cell_index_type target_top = target.add_cell ("CLIP_TOP"); for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) { builder.reset (); unsigned int li1 = (*li).first; unsigned int target_layer = target.insert_layer (*(*li).second); builder.set_target_layer (target_layer); db::cell_index_type top_cell_index = *ly.begin_top_down (); db::Region reg; reg.insert (db::Box (5000, 13000, 18500, 20000)); reg.insert (db::Box (11000, 20000, 18500, 36000)); reg.merge (); db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, reg); iter.push (&builder); target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ())); } CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/hierarchy_builder_au8b.gds"); }