Hierarchical area and perimeter and sizing

Area and perimeter computation happens hierarchically
now. Magnified instances are supported.

Sizing is implemented hierarchically.

For anisotropic sizing, orientation variants may be
generated. For both isotropic and anisotropic
magnification variants will be created.
This commit is contained in:
Matthias Koefferlein 2019-02-09 19:13:54 +01:00
parent bbf7b2768b
commit 1f3af7bbfe
12 changed files with 363 additions and 21 deletions

View File

@ -165,7 +165,7 @@ public:
/**
* @brief Collects cell variants for the given layout starting from the top cell
*/
void collect (db::Layout &layout, db::Cell &top_cell)
void collect (const db::Layout &layout, const db::Cell &top_cell)
{
// The top cell gets a "variant" with unit transformation
m_variants [top_cell.cell_index ()].insert (std::make_pair (db::ICplxTrans (), 1));

View File

@ -33,6 +33,7 @@
#include "dbHierNetworkProcessor.h"
#include "dbCellGraphUtils.h"
#include "dbPolygonTools.h"
#include "dbCellVariants.h"
#include "tlTimer.h"
namespace db
@ -382,7 +383,7 @@ DeepRegion::ensure_merged_polygons_valid () const
ClusterMerger cm (m_deep_layer.layer (), hc, min_coherence (), report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity ());
// @@@ iterate only over the called cells?
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::PolygonRef> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::PolygonRef>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
@ -630,23 +631,29 @@ DeepRegion::area (const db::Box &box) const
ensure_merged_polygons_valid ();
// @@@ scaled instances!
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
DeepRegion::area_type a = 0;
const db::Layout &layout = m_merged_polygons.layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
DeepRegion::area_type ac = 0;
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
ac += s->area ();
}
a += cc.weight (*c) * ac;
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (*c);
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
double mag = v->first.mag ();
a += v->second * ac * mag * mag;
}
}
return a;
} else {
// In the clipped case fall back to flat mode
return db::AsIfFlatRegion::area (box);
}
}
@ -658,23 +665,29 @@ DeepRegion::perimeter (const db::Box &box) const
ensure_merged_polygons_valid ();
// @@@ scaled instances!
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
DeepRegion::perimeter_type p = 0;
const db::Layout &layout = m_merged_polygons.layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
DeepRegion::perimeter_type pc = 0;
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
pc += s->perimeter ();
}
p += cc.weight (*c) * pc;
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (*c);
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
double mag = v->first.mag ();
p += v->second * pc * mag;
}
}
return p;
} else {
// In the clipped case fall back to flat mode
return db::AsIfFlatRegion::perimeter (box);
}
}
@ -810,15 +823,27 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
db::Layout &layout = m_merged_polygons.layout ();
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
double mag = v.begin ()->first.mag ();
db::Coord d_with_mag = db::coord_traits<db::Coord>::rounded (d / mag);
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::ShapeGenerator pc (st, false /*no clear - already empty*/);
db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/);
db::SizingPolygonFilter siz (pg2, d, d, mode);
db::SizingPolygonFilter siz (pg2, d_with_mag, d_with_mag, mode);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
@ -831,14 +856,79 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
return res.release ();
}
namespace
{
struct DB_PUBLIC XYAnisotropyAndMagnificationReducer
{
typedef tl::true_tag is_translation_invariant;
db::ICplxTrans operator () (const db::ICplxTrans &trans) const
{
double a = trans.angle ();
if (a > 180.0 - db::epsilon) {
a -= 180.0;
}
return db::ICplxTrans (trans.mag (), a, false, db::Vector ());
}
db::Trans operator () (const db::Trans &trans) const
{
return db::Trans (trans.angle () % 2, false, db::Vector ());
}
};
}
RegionDelegate *
DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
{
if (dx == dy) {
return sized (dx, mode);
} else {
return db::AsIfFlatRegion::sized (dx, dy, mode);
}
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
db::XYAnisotropyAndMagnificationReducer red;
db::cell_variants_collector<db::XYAnisotropyAndMagnificationReducer> vars (red);
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
double mag = v.begin ()->first.mag ();
double angle = v.begin ()->first.angle ();
db::Coord dx_with_mag = db::coord_traits<db::Coord>::rounded (dx / mag);
db::Coord dy_with_mag = db::coord_traits<db::Coord>::rounded (dy / mag);
if (fabs (angle - 90.0) < 45.0) {
// TODO: how to handle x/y swapping on arbitrary angles?
std::swap (dx_with_mag, dy_with_mag);
}
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::ShapeGenerator pc (st, false /*no clear - already empty*/);
db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/);
db::SizingPolygonFilter siz (pg2, dx_with_mag, dy_with_mag, mode);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
siz.put (poly);
}
}
return res.release ();
}
RegionDelegate *

View File

@ -396,6 +396,19 @@ DeepShapeStore::invalidate_hier ()
m_delivery_mapping_cache.clear ();
}
void
DeepShapeStore::issue_variants (unsigned int layout_index, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_map)
{
invalidate_hier ();
db::HierarchyBuilder &builder = m_layouts [layout_index]->builder;
for (std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator i = var_map.begin (); i != var_map.end (); ++i) {
for (std::map<db::ICplxTrans, db::cell_index_type>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
builder.register_variant (i->first, j->second);
}
}
}
const db::CellMapping &
DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells)
{
@ -431,8 +444,8 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
HierarchyBuilder::cell_map_type::const_iterator mm = m;
++mm;
bool skip = false;
while (mm != original_builder.end_cell_map () && mm->first.first == m->first.first) {
bool skip = original_builder.is_variant (m->second); // skip variant cells
while (mm != original_builder.end_cell_map () && mm->first.first == m->first.first && ! skip) {
// we have cell variants and cannot simply map
++mm;
++m;

View File

@ -153,6 +153,12 @@ public:
*/
DeepLayer copy () const;
/**
* @brief Separates cell variants (see DeepShapeStore::separate_variants)
*/
template <class VarCollector>
void separate_variants (VarCollector &collector);
/**
* @brief Gets the shape store object
* This is a pure const version to prevent manipulation of the store.
@ -250,6 +256,27 @@ public:
*/
const db::CellMapping &cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells = 0);
/**
* @brief Create cell variants from the given variant collector
*
* To use this method, first create a variant collector (db::cell_variant_collector) with the required
* reducer and collect the variants. Then call this method on the desired layout index to create the variants.
*/
template <class VarCollector>
void separate_variants (unsigned int layout_index, VarCollector &coll)
{
tl_assert (is_valid_layout_index (layout_index));
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > var_map;
coll.separate_variants (layout (layout_index), initial_cell (layout_index), &var_map);
if (var_map.empty ()) {
// nothing to do.
return;
}
issue_variants (layout_index, var_map);
}
/**
* @brief For testing
*/
@ -434,6 +461,8 @@ private:
void require_singular () const;
void issue_variants (unsigned int layout, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_map);
typedef std::map<db::RecursiveShapeIterator, unsigned int, RecursiveShapeIteratorCompareForTargetHierarchy> layout_map_type;
// no copying
@ -478,6 +507,13 @@ private:
std::map<DeliveryMappingCacheKey, db::CellMapping> m_delivery_mapping_cache;
};
template <class VarCollector>
void DeepLayer::separate_variants (VarCollector &collector)
{
check_dss ();
mp_store->separate_variants (m_layout, collector);
}
}
namespace tl

View File

@ -172,6 +172,19 @@ HierarchyBuilder::reset ()
m_cm_new_entry = false;
}
void
HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var)
{
// non_var (despite it's name) may be a variant created previously.
variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (non_var);
if (v != m_variants_to_original_target_map.end ()) {
non_var = v->second;
}
m_original_targets_to_variants_map [non_var].push_back (var);
m_variants_to_original_target_map.insert (std::make_pair (var, non_var));
}
void
HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
{
@ -203,7 +216,8 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
// We can do so as the recursive shape iterator will always deliver all instances
// and not a partial set of instances.
m_cm_new_entry = new_top.begin ().at_end ();
m_cell_stack.push_back (std::make_pair (m_cm_new_entry, &new_top));
m_cell_stack.push_back (std::make_pair (m_cm_new_entry, std::vector<db::Cell *> ()));
m_cell_stack.back ().second.push_back (&new_top);
}
void
@ -213,7 +227,7 @@ HierarchyBuilder::end (const RecursiveShapeIterator *iter)
m_initial_pass = false;
m_cells_seen.clear ();
mp_initial_cell = m_cell_stack.empty () ? 0 : m_cell_stack.front ().second;
mp_initial_cell = m_cell_stack.empty () ? 0 : m_cell_stack.front ().second.front ();
m_cell_stack.clear ();
m_cm_entry = cell_map_type::const_iterator ();
m_cm_new_entry = false;
@ -231,7 +245,16 @@ HierarchyBuilder::enter_cell (const RecursiveShapeIterator * /*iter*/, const db:
m_cells_to_be_filled.erase (m_cm_entry->second);
}
m_cell_stack.push_back (std::make_pair (new_cell, &mp_target->cell (m_cm_entry->second)));
m_cell_stack.push_back (std::make_pair (new_cell, std::vector<db::Cell *> ()));
original_target_to_variants_map_type::const_iterator v = m_original_targets_to_variants_map.find (m_cm_entry->second);
if (v != m_original_targets_to_variants_map.end ()) {
for (std::vector<db::cell_index_type>::const_iterator i = v->second.begin (); i != v->second.end (); ++i) {
m_cell_stack.back ().second.push_back (&mp_target->cell (*i));
}
} else {
m_cell_stack.back ().second.push_back (&mp_target->cell (m_cm_entry->second));
}
}
void
@ -260,7 +283,9 @@ HierarchyBuilder::new_inst (const RecursiveShapeIterator *iter, const db::CellIn
if (m_cell_stack.back ().first) {
db::CellInstArray new_inst (inst, &mp_target->array_repository ());
new_inst.object () = db::CellInst (m_cm_entry->second);
m_cell_stack.back ().second->insert (new_inst);
for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
(*c)->insert (new_inst);
}
}
// To see the cell once, use NI_single. If we did see the cell already, skip the whole instance array.
@ -307,7 +332,9 @@ HierarchyBuilder::new_inst_member (const RecursiveShapeIterator *iter, const db:
// for a new cell, create this instance
if (m_cell_stack.back ().first) {
db::CellInstArray new_inst (db::CellInst (m_cm_entry->second), trans);
m_cell_stack.back ().second->insert (new_inst);
for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
(*c)->insert (new_inst);
}
}
return (m_cells_seen.find (key) == m_cells_seen.end ());
@ -318,8 +345,10 @@ HierarchyBuilder::new_inst_member (const RecursiveShapeIterator *iter, const db:
void
HierarchyBuilder::shape (const RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*trans*/, const db::Box &region, const box_tree_type *complex_region)
{
db::Shapes &shapes = m_cell_stack.back ().second->shapes (m_target_layer);
mp_pipe->push (shape, region, complex_region, &shapes);
for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
db::Shapes &shapes = (*c)->shapes (m_target_layer);
mp_pipe->push (shape, region, complex_region, &shapes);
}
}
// ---------------------------------------------------------------------------------------------

View File

@ -169,6 +169,8 @@ class DB_PUBLIC HierarchyBuilder
public:
typedef std::map<std::pair<db::cell_index_type, std::set<db::Box> >, db::cell_index_type> cell_map_type;
typedef std::map<db::cell_index_type, std::vector<db::cell_index_type> > original_target_to_variants_map_type;
typedef std::map<db::cell_index_type, db::cell_index_type> variant_to_original_target_map_type;
HierarchyBuilder (db::Layout *target, unsigned int target_layer, HierarchyBuilderShapeReceiver *pipe = 0);
HierarchyBuilder (db::Layout *target, HierarchyBuilderShapeReceiver *pipe = 0);
@ -241,18 +243,37 @@ public:
return m_cell_map.end ();
}
/**
* @brief Marks a cell as a variant of another
*
* The first cell is either the original, non-variant target cell or itself a variant.
* The second cell will be registered as a variant of the first one.
*/
void register_variant (db::cell_index_type non_var, db::cell_index_type var);
/**
* @brief Gets a value indicating whether the given cell is a variant cell
*/
bool is_variant (db::cell_index_type ci) const
{
return m_variants_to_original_target_map.find (ci) != m_variants_to_original_target_map.end ();
}
private:
tl::weak_ptr<db::Layout> mp_target;
HierarchyBuilderShapeReceiver *mp_pipe;
bool m_initial_pass;
db::RecursiveShapeIterator m_source;
cell_map_type m_cell_map;
original_target_to_variants_map_type m_original_targets_to_variants_map;
variant_to_original_target_map_type m_variants_to_original_target_map;
std::set<cell_map_type::key_type> m_cells_seen;
std::set<db::cell_index_type> m_cells_to_be_filled;
cell_map_type::const_iterator m_cm_entry;
bool m_cm_new_entry;
unsigned int m_target_layer;
std::vector<std::pair<bool, db::Cell *> > m_cell_stack;
std::vector<std::pair<bool, std::vector<db::Cell *> > > m_cell_stack;
db::Cell *mp_initial_cell;
};

View File

@ -381,7 +381,160 @@ TEST(7_Merge)
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au7.gds");
}
TEST(8_AreaAndPerimeter)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_area_peri_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::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
dss.set_max_vertex_count (4);
dss.set_threads (0);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
EXPECT_EQ (r1.area (), db::coord_traits<db::Coord>::area_type (9722000000));
EXPECT_EQ (r1.perimeter (), db::coord_traits<db::Coord>::perimeter_type (1360000));
EXPECT_EQ (r1.area (r1.bbox ()), db::coord_traits<db::Coord>::area_type (9722000000));
EXPECT_EQ (r1.perimeter (r1.bbox ()), db::coord_traits<db::Coord>::perimeter_type (1360000));
EXPECT_EQ (r1.area (db::Box (40000, -90000, 50000, -80000)), db::coord_traits<db::Coord>::area_type (100000000));
EXPECT_EQ (r1.perimeter (db::Box (40000, -90000, 50000, -80000)), db::coord_traits<db::Coord>::perimeter_type (0));
EXPECT_EQ (r1.area (db::Box (-40000, -90000, -50000, -80000)), db::coord_traits<db::Coord>::area_type (0));
}
TEST(9_SizingSimple)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_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::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
dss.set_max_vertex_count (4);
dss.set_threads (0);
unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0));
db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss);
db::Region r6_sized = r6.sized (-50);
db::Region r6_sized_aniso = r6.sized (-20, -100);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r6);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r6_sized);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r6_sized_aniso);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au9a.gds");
}
TEST(9_SizingWithScaleVariants)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_area_peri_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::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
dss.set_max_vertex_count (4);
dss.set_threads (0);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r1_sized = r1.sized (-2000);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1_sized);
// copy another layer - this challenges the ability to map to multiple variants
unsigned int l1b = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1b (db::RecursiveShapeIterator (ly, top_cell, l1b), dss);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1b.merged ());
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au9b.gds");
}
TEST(9_SizingWithScaleAndXYVariants)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_area_peri_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::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
dss.set_max_vertex_count (4);
dss.set_threads (0);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r1_sized = r1.sized (-2000);
db::Region r1_sized_aniso = r1.sized (-1000, -2000);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1_sized);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r1_sized_aniso);
// copy another layer - this challenges the ability to map to multiple variants
unsigned int l1b = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1b (db::RecursiveShapeIterator (ly, top_cell, l1b), dss);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1b.merged ());
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au9c.gds");
// merge back to original - this challenges the ability to map back the variants
ly.insert (top_cell_index, ly.get_layer (db::LayerProperties (11, 0)), r1_sized);
ly.insert (top_cell_index, ly.get_layer (db::LayerProperties (12, 0)), r1_sized_aniso);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au9d.gds");
}
TEST(100_Integration)
{

Binary file not shown.

BIN
testdata/algo/deep_region_au9a.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au9b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au9c.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au9d.gds vendored Normal file

Binary file not shown.