WIP: deep region debugged, GSI binding, tests.

This commit is contained in:
Matthias Koefferlein 2018-11-17 00:16:13 +01:00
parent f5cc8b6018
commit a438dfd6f0
25 changed files with 699 additions and 71 deletions

View File

@ -1447,6 +1447,15 @@ AsIfFlatRegion::add (const Region &other) const
}
}
void
AsIfFlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
shapes.insert (*p);
}
}
bool
AsIfFlatRegion::equals (const Region &other) const
{

View File

@ -201,6 +201,8 @@ public:
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
protected:
void update_bbox (const db::Box &box);
void invalidate_bbox ();

View File

@ -179,6 +179,17 @@ public:
return m_b2a_mapping;
}
/**
* @brief Creates mappings for all cells not mapped yet
*
* When constructing a cell mapping by explicit mapping (map (a, b)), some cells may be
* left unmapped. This method allows creating mappings for these missing cells by adding
* new cells and the corresponding instances into the target layout_a.
*
* The returned vector lists the new cells.
*/
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b);
private:
void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand,
std::map<db::cell_index_type, db::cell_index_type> &unique_mapping,
@ -187,8 +198,6 @@ private:
void dump_mapping (const std::map <db::cell_index_type, std::vector<db::cell_index_type> > &candidates,
const db::Layout &layout_a, const db::Layout &layout_b);
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b);
std::map <db::cell_index_type, db::cell_index_type> m_b2a_mapping;
};

View File

@ -31,17 +31,73 @@
namespace db
{
namespace
{
/**
* @brief An iterator delegate for the deep region
* TODO: this is kind of redundant with OriginalLayerIterator ..
*/
class DB_PUBLIC DeepRegionIterator
: public RegionIteratorDelegate
{
public:
typedef db::Polygon value_type;
DeepRegionIterator (const db::RecursiveShapeIterator &iter)
: m_iter (iter)
{
set ();
}
virtual bool at_end () const
{
return m_iter.at_end ();
}
virtual void increment ()
{
++m_iter;
set ();
}
virtual const value_type *get () const
{
return &m_polygon;
}
virtual RegionIteratorDelegate *clone () const
{
return new DeepRegionIterator (*this);
}
private:
friend class Region;
db::RecursiveShapeIterator m_iter;
mutable value_type m_polygon;
void set () const
{
if (! m_iter.at_end ()) {
m_iter.shape ().polygon (m_polygon);
m_polygon.transform (m_iter.trans (), false);
}
}
};
}
// -------------------------------------------------------------------------------------------------------------
// DeepRegion implementation
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count))
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons (false)
{
init ();
}
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics, double area_ratio, size_t max_vertex_count)
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count))
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons (false)
{
init ();
@ -223,5 +279,11 @@ DeepRegion::ensure_merged_polygons_valid () const
}
}
void
DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
m_deep_layer.insert_into (layout, into_cell, into_layer);
}
}

View File

@ -32,57 +32,7 @@
namespace db {
/**
* @brief An iterator delegate for the deep region
*/
class DB_PUBLIC DeepRegionIterator
: public RegionIteratorDelegate
{
public:
typedef db::Polygon value_type;
DeepRegionIterator (const db::RecursiveShapeIterator &iter)
: m_iter (iter)
{
set ();
}
virtual bool at_end () const
{
return m_iter.at_end ();
}
virtual void increment ()
{
++m_iter;
set ();
}
virtual const value_type *get () const
{
return &m_tmp;
}
virtual RegionIteratorDelegate *clone () const
{
return new DeepRegionIterator (*this);
}
private:
friend class Region;
db::RecursiveShapeIterator m_iter;
mutable value_type m_tmp;
void set () const
{
if (! m_iter.at_end ()) {
m_iter->polygon (m_tmp);
}
}
};
/**
* @brief A flat, polygon-set delegate
* @brief A deep, polygon-set delegate
*/
class DB_PUBLIC DeepRegion
: public AsIfFlatRegion
@ -120,6 +70,8 @@ public:
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
protected:
virtual void merged_semantics_changed ();

View File

@ -22,6 +22,9 @@
#include "dbDeepShapeStore.h"
#include "dbCellMapping.h"
#include "dbLayoutUtils.h"
#include "tlTimer.h"
namespace db
@ -47,16 +50,57 @@ DeepLayer::DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int l
// .. nothing yet ..
}
// ----------------------------------------------------------------------------------
DeepShapeStore::DeepShapeStore ()
DeepLayer::~DeepLayer ()
{
// .. nothing yet ..
}
void
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
check_dss ();
const_cast<db::DeepShapeStore *> (mp_store.get ())->insert (*this, into_layout, into_cell, into_layer);
}
db::Layout *
DeepLayer::layout ()
{
check_dss ();
return mp_store->layout (m_layout);
}
const db::Layout *
DeepLayer::layout () const
{
check_dss ();
return const_cast<db::DeepShapeStore *> (mp_store.get ())->layout (m_layout);
}
void
DeepLayer::check_dss () const
{
if (mp_store.get () == 0) {
throw tl::Exception (tl::to_string (tr ("Heap lost: the DeepShapeStore container no longer exists")));
}
}
// ----------------------------------------------------------------------------------
static size_t s_instance_count = 0;
DeepShapeStore::DeepShapeStore ()
{
++s_instance_count;
}
DeepShapeStore::~DeepShapeStore ()
{
// .. nothing yet ..
--s_instance_count;
}
size_t DeepShapeStore::instance_count ()
{
return s_instance_count;
}
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
@ -108,5 +152,86 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
return DeepLayer (this, layout_index, layer_index);
}
void
DeepShapeStore::insert (const DeepLayer &deep_layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer)
{
const db::Layout *source_layout = deep_layer.layout ();
if (source_layout->begin_top_down () == source_layout->end_top_cells ()) {
// empty source - nothing to do.
return;
}
db::cell_index_type source_top = *source_layout->begin_top_down();
db::HierarchyBuilder &original_builder = m_builders [deep_layer.layout_index ()];
// derive a cell mapping for source to target. We employ a
DeliveryMappingCacheKey key (deep_layer.layout_index (), into_layout, into_cell);
std::map<DeliveryMappingCacheKey, db::CellMapping>::iterator cm = m_delivery_mapping_cache.find (key);
if (cm == m_delivery_mapping_cache.end ()) {
cm = m_delivery_mapping_cache.insert (std::make_pair (key, db::CellMapping ())).first;
if (into_layout == original_builder.source ().layout () && &into_layout->cell (into_cell) == original_builder.source ().top_cell ()) {
// This is the case of mapping back to the original. In this case we can use the information
// provided inside the original hierarchy builders. They list the source cells and the target cells
// create from them. We need to consider however, that the hierarchy builder is allowed to create
// variants which we cannot map.
bool any_skipped = false;
for (HierarchyBuilder::cell_map_type::const_iterator m = original_builder.begin_cell_map (); m != original_builder.end_cell_map (); ++m) {
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) {
// we have cell variants and cannot simply map
++mm;
++m;
skip = true;
}
if (! skip) {
cm->second.map (m->first.first, m->second);
} else {
any_skipped = true;
}
}
if (any_skipped) {
// Add new cells for the variants
cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top);
}
} else if (into_layout->cells () == 1) {
// Another simple case is mapping into an empty (or single-top-cell-only) layout, where we can use "create_from_single_full".
cm->second.create_single_mapping_full (*into_layout, into_cell, *source_layout, source_top);
} else {
cm->second.create_from_geometry_full (*into_layout, into_cell, *source_layout, source_top);
}
}
// Actually copy the shapes
db::ICplxTrans trans (source_layout->dbu () / into_layout->dbu ());
std::map<unsigned int, unsigned int> lm;
lm.insert (std::make_pair (deep_layer.layer (), into_layer));
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_top);
db::copy_shapes (*into_layout, *source_layout, trans, source_cells, cm->second.table (), lm);
}
}

View File

@ -31,6 +31,7 @@
#include "dbLayout.h"
#include "dbRecursiveShapeIterator.h"
#include "dbHierarchyBuilder.h"
#include "gsiObject.h"
#include <set>
#include <map>
@ -87,6 +88,19 @@ public:
return m_layer;
}
/**
* @brief Gets the layout index
*/
unsigned int layout_index () const
{
return m_layout;
}
/**
* @brief Inserts the layer into the given layout, starting from the given cell and into the given layer
*/
void insert_into (Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const;
private:
friend class DeepShapeStore;
@ -95,6 +109,8 @@ private:
*/
DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int layer);
void check_dss () const;
tl::weak_ptr<DeepShapeStore> mp_store;
unsigned int m_layout;
unsigned int m_layer;
@ -121,7 +137,7 @@ struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy
* algorithms for doing the preparation and transfer.
*/
class DB_PUBLIC DeepShapeStore
: public tl::Object
: public tl::Object, public gsi::ObjectBase
{
public:
/**
@ -146,7 +162,24 @@ public:
*/
DeepLayer create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio = 3.0, size_t max_vertex_count = 16);
/**
* @brief Inserts the deep layer's into some target layout
*/
void insert (const DeepLayer &layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer);
/**
* @brief For testing
*/
static size_t instance_count ();
private:
friend class DeepLayer;
db::Layout *layout (unsigned int n)
{
return &m_layouts [n];
}
typedef std::map<db::RecursiveShapeIterator, unsigned int, RecursiveShapeIteratorCompareForTargetHierarchy> layout_map_type;
// no copying
@ -156,9 +189,47 @@ private:
tl::stable_vector<db::Layout> m_layouts;
tl::stable_vector<db::HierarchyBuilder> m_builders;
layout_map_type m_layout_map;
struct DeliveryMappingCacheKey
{
// NOTE: we shouldn't keep pointers here as the layouts may get deleted and recreated with the same address.
// But as we don't access these objects that's fairly safe.
DeliveryMappingCacheKey (unsigned int _from_index, db::Layout *_into_layout, db::cell_index_type _into_cell)
: from_index (_from_index), into_layout (_into_layout), into_cell (_into_cell)
{
// .. nothing yet ..
}
bool operator< (const DeliveryMappingCacheKey &other) const
{
if (from_index != other.from_index) {
return from_index < other.from_index;
}
if (into_layout != other.into_layout) {
return into_layout < other.into_layout;
}
return into_cell <other.into_cell;
}
unsigned int from_index;
db::Layout *into_layout;
db::cell_index_type into_cell;
};
std::map<DeliveryMappingCacheKey, db::CellMapping> m_delivery_mapping_cache;
};
}
namespace tl
{
// disable copying of the deep shape store object
template <> struct type_traits <db::DeepShapeStore> : public type_traits<void> {
typedef tl::false_tag has_copy_constructor;
};
}
#endif

View File

@ -120,6 +120,8 @@ public:
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { }
private:
EmptyRegion &operator= (const EmptyRegion &other);
};

View File

@ -362,6 +362,11 @@ const db::RecursiveShapeIterator *FlatRegion::iter () const
return 0;
}
void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
layout->cell (into_cell).shapes (into_layer).insert (m_polygons);
}
void
FlatRegion::insert (const db::Box &box)
{

View File

@ -109,6 +109,8 @@ public:
virtual size_t size () const;
virtual bool is_merged () const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual RegionDelegate *merged_in_place ();
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc);
virtual RegionDelegate *merged () const;

View File

@ -62,16 +62,19 @@ compare_iterators_with_respect_to_target_hierarchy (const db::RecursiveShapeIter
if (iter1.has_complex_region () && iter1.complex_region () != iter2.complex_region ()) {
return iter1.complex_region () < iter2.complex_region () ? -1 : 1;
}
if (iter1.region () != iter2.region ()) {
return iter1.region () < iter2.region () ? -1 : 1;
}
if (iter1.multiple_layers () != iter2.multiple_layers ()) {
return iter1.multiple_layers () < iter2.multiple_layers () ? -1 : 1;
}
if (iter1.multiple_layers ()) {
if (iter1.layers () != iter2.layers ()) {
return iter1.layers () < iter2.layers ();
return iter1.layers () < iter2.layers () ? -1 : 1;
}
} else {
if (iter1.layer () != iter2.layer ()) {
return iter1.layer () < iter2.layer ();
return iter1.layer () < iter2.layer () ? -1 : 1;
}
}
}
@ -161,9 +164,9 @@ void
HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
{
if (m_initial_pass) {
m_ref_iter = *iter;
m_source = *iter;
} else {
tl_assert (compare_iterators_with_respect_to_target_hierarchy (m_ref_iter, *iter) == 0);
tl_assert (compare_iterators_with_respect_to_target_hierarchy (m_source, *iter) == 0);
}
m_cell_stack.clear ();

View File

@ -41,7 +41,7 @@ namespace db
* This function will return -1, 0 or 1 depending on whether the two iterators
* can be used with the same builder (0) or whether they are less (-1) or greater (1).
*/
int compare_iterators_with_respect_to_target_hierarchy (const db::RecursiveShapeIterator &iter1, const db::RecursiveShapeIterator &iter2);
int DB_PUBLIC compare_iterators_with_respect_to_target_hierarchy (const db::RecursiveShapeIterator &iter1, const db::RecursiveShapeIterator &iter2);
/**
* @brief A class to receive shapes from the hierarchy builder
@ -199,18 +199,50 @@ public:
void reset ();
/**
* @brief Gets the initial cell the builder produced
* @brief Gets the initial cell the builder produced in the target layout
*/
db::Cell *initial_cell ()
{
return mp_initial_cell;
}
/**
* @brief Gets the target layout
*/
db::Layout *target ()
{
return mp_target.get ();
}
/**
* @brief Gets the recursive shape iterator the data was taken from
*/
const db::RecursiveShapeIterator &source () const
{
return m_source;
}
/**
* @brief Gets the iterator for the cell map
*/
cell_map_type::const_iterator begin_cell_map () const
{
return m_cell_map.begin ();
}
/**
* @brief Gets the iterator for the cell map (end)
*/
cell_map_type::const_iterator end_cell_map () const
{
return m_cell_map.end ();
}
private:
tl::weak_ptr<db::Layout> mp_target;
HierarchyBuilderShapeReceiver *mp_pipe;
bool m_initial_pass;
db::RecursiveShapeIterator m_ref_iter;
db::RecursiveShapeIterator m_source;
cell_map_type m_cell_map;
std::set<cell_map_type::key_type> m_cells_seen;
cell_map_type::const_iterator m_cm_entry;

View File

@ -31,6 +31,7 @@
#include "dbLibraryProxy.h"
#include "dbLibraryManager.h"
#include "dbLibrary.h"
#include "dbRegion.h"
#include "tlTimer.h"
#include "tlLog.h"
#include "tlInternational.h"
@ -638,6 +639,12 @@ Layout::delete_cell (cell_index_type id)
}
}
void
Layout::insert (db::cell_index_type cell, int layer, const db::Region &region)
{
region.insert_into (this, cell, layer);
}
void
Layout::flatten (const db::Cell &source_cell, db::Cell &target_cell, const db::ICplxTrans &t, int levels)
{

View File

@ -61,6 +61,7 @@ class Library;
class LibraryProxy;
class CellMapping;
class LayerMapping;
class Region;
template <class Coord> class generic_repository;
typedef generic_repository<db::Coord> GenericRepository;
@ -1090,6 +1091,15 @@ public:
*/
void flatten (db::Cell &cell, int levels, bool prune = false);
/**
* @brief Inserts a region (potentially hierarchical) into the given cell and layer
*
* If the region is flat (conceptionally), it will be put into the cell.
* If the region is hierarchical, a cell hierarchy will be built below the
* given cell.
*/
void insert (db::cell_index_type cell, int layer, const db::Region &region);
/**
* @brief Delete a cell plus all subcells
*

View File

@ -1685,6 +1685,14 @@ public:
return mp_delegate->less (other);
}
/**
* @brief Less operator
*/
void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
return mp_delegate->insert_into (layout, into_cell, into_layer);
}
private:
friend class Edges;
friend class EdgePairs;

View File

@ -179,6 +179,8 @@ public:
virtual bool equals (const Region &other) const = 0;
virtual bool less (const Region &other) const = 0;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const = 0;
protected:
const std::string &progress_desc () const
{

View File

@ -1356,7 +1356,6 @@ static std::vector<db::cell_index_type> copy_tree (db::Cell *cell, const db::Cel
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::CellMapping cm;
@ -1387,7 +1386,6 @@ static void copy_tree_shapes2 (db::Cell *cell, const db::Cell &source_cell, cons
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::LayerMapping lm;
@ -1413,7 +1411,6 @@ static void copy_tree_shapes3 (db::Cell *cell, const db::Cell &source_cell, cons
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
std::vector <db::cell_index_type> source_cells;

View File

@ -32,6 +32,7 @@
#include "dbLibraryManager.h"
#include "dbPCellDeclaration.h"
#include "dbHash.h"
#include "dbRegion.h"
#include "tlStream.h"
namespace gsi
@ -1179,6 +1180,18 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"This method has been introduced in version 0.20.\n"
) +
gsi::method ("insert", (void (db::Layout::*) (db::cell_index_type, unsigned int, const db::Region &)) &db::Layout::insert,
gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
"@brief Inserts a region into the given cell and layer\n"
"If the region is (conceptionally) a flat region, it will be inserted into the cell's shapes "
"list as a flat sequence of polygons.\n"
"If the region is a deep (hierarchical) region, it will create a subhierarchy below the given "
"cell and it's shapes will be put into the respective cells. Suitable subcells will be picked "
"for inserting the shapes. If a hierarchy already exists below the given cell, the algorithm will "
"try to reuse this hierarchy.\n"
"\n"
"This method has been introduced in version 0.26.\n"
) +
gsi::method_ext ("flatten", &flatten,
"@brief Flattens the given cell\n"
"@args cell_index, levels, prune\n"

View File

@ -26,6 +26,8 @@
#include "dbPolygonTools.h"
#include "dbLayoutUtils.h"
#include "dbShapes.h"
#include "dbDeepShapeStore.h"
#include "dbRegion.h"
#include "tlGlobPattern.h"
#include <memory>
@ -213,6 +215,11 @@ static db::Region *new_si (const db::RecursiveShapeIterator &si)
return new db::Region (si);
}
static db::Region *new_sid (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
{
return new db::Region (si, dss, area_ratio, max_vertex_count);
}
static db::Region *new_si2 (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
{
return new db::Region (si, trans);
@ -712,6 +719,25 @@ static Container *decompose_trapezoids (const db::Region *r, int mode)
int td_simple ();
int po_any ();
Class<db::DeepShapeStore> decl_DeepShapeStore ("db", "DeepShapeStore",
method ("instance_count", db::DeepShapeStore::instance_count, "@hide"),
"@brief An opaque layout heap for the deep region processor\n"
"\n"
"This class is used for keeping intermediate, hierarchical data for the "
"deep region processor. It is used in conjunction with the region "
"constructor to create a deep (hierarchical) region."
"\n"
"@code\n"
"layout = ... # a layout\n"
"layer = ... # a layer\n"
"cell = ... # a cell (initial cell for the deep region)\n"
"dss = RBA::DeepShapeStore::new\n"
"region = RBA::Region::new(cell.begin(layer), dss)\n"
"@/code\n"
"\n"
"This class has been introduced in version 0.26.\n"
);
Class<db::Region> decl_Region ("db", "Region",
constructor ("new", &new_v,
"@brief Default constructor\n"
@ -789,6 +815,22 @@ Class<db::Region> decl_Region ("db", "Region",
"r = RBA::Region::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n"
"@/code\n"
) +
constructor ("new", &new_sid, gsi::arg ("shape_iterator"), gsi::arg ("deep_shape_store"), gsi::arg ("area_ratio", 3.0), gsi::arg ("max_vertex_count", size_t (16)),
"@brief Constructor for a deep region from a hierarchical shape set\n"
"\n"
"This constructor creates a hierarchical region. Use a \\DeepShapeStore object to "
"supply the hierarchical heap. See \\DeepShapeStore for more details.\n"
"\n"
"'area_ratio' and 'max_vertex' supply two optimization parameters which control how "
"big polygons are split to reduce the region's polygon complexity.\n"
"\n"
"@param shape_iterator The recursive shape iterator which delivers the hierarchy to take\n"
"@param deep_shape_store The hierarchical heap (see there)\n"
"@param area_ratio The maximum ratio of bounding box to polygon area before polygons are split\n"
"@param"
"\n"
"This method has been introduced in version 0.26.\n"
) +
constructor ("new", &new_texts<BoxDelivery>, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true),
"@brief Constructor from a text set\n"
"\n"

View File

@ -0,0 +1,113 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2018 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 "dbDeepShapeStore.h"
#include "tlUnitTest.h"
#include "tlStream.h"
TEST(1)
{
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::DeepShapeStore dss;
db::Layout target;
// deliberately using vector to force reallocation ...
std::vector<db::Region> regions;
std::vector<unsigned int> target_layers;
for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) {
unsigned int li1 = (*li).first;
db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1);
target_layers.push_back (target.insert_layer (*(*li).second));
regions.push_back (db::Region (iter, dss));
}
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
for (std::vector<db::Region>::const_iterator r = regions.begin (); r != regions.end (); ++r) {
target.insert (target_top_cell_index, target_layers [r - regions.begin ()], *r);
}
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au1.gds");
}
TEST(2)
{
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::DeepShapeStore dss;
db::Layout target;
// deliberately using vector to force reallocation ...
std::vector<std::pair<db::Region, unsigned int> > regions;
for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) {
unsigned int li1 = (*li).first;
unsigned int tl = target.insert_layer (*(*li).second);
db::RecursiveShapeIterator iter1 (ly, ly.cell (top_cell_index), li1, db::Box (2000, -1000, 6000, 4000));
regions.push_back (std::make_pair (db::Region (iter1, dss), tl));
db::RecursiveShapeIterator iter2 (ly, ly.cell (top_cell_index), li1, db::Box (14000, 0, 20000, 3000));
regions.push_back (std::make_pair (db::Region (iter2, dss), tl));
}
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
for (std::vector<std::pair<db::Region, unsigned int> >::const_iterator r = regions.begin (); r != regions.end (); ++r) {
target.insert (target_top_cell_index, r->second, r->first);
}
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au1.gds");
}

View File

@ -335,3 +335,135 @@ TEST(4_ComplexRegionAndLayoutWithClip)
db::compare_layouts (_this, target, tl::testsrc () + "/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<unsigned int> 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<unsigned int> 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);
}
}

View File

@ -55,7 +55,8 @@ SOURCES = \
dbSaveLayoutOptionsTests.cc \
dbHierarchyBuilderTests.cc \
dbRecursiveShapeIteratorTests.cc \
dbHierProcessorTests.cc
dbHierProcessorTests.cc \
dbDeepRegionTests.cc
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC

BIN
testdata/algo/deep_region_au1.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_l1.gds vendored Normal file

Binary file not shown.

View File

@ -769,6 +769,35 @@ class DBRegion_TestClass < TestBase
end
# deep region tests
def test_deep1
# construction/destruction magic ...
GC.start
assert_equal(RBA::DeepShapeStore::instance_count, 0)
dss = RBA::DeepShapeStore::new
dss._create
assert_equal(RBA::DeepShapeStore::instance_count, 1)
dss = nil
GC.start
assert_equal(RBA::DeepShapeStore::instance_count, 0)
dss = RBA::DeepShapeStore::new
ly = RBA::Layout::new
ly.read(File.join($ut_testsrc, "testdata", "algo", "deep_region_l1.gds"))
l1 = ly.layer(1, 0)
r = RBA::Region::new(ly.top_cell.begin_shapes_rec(l1), dss)
rf = RBA::Region::new(ly.top_cell.begin_shapes_rec(l1))
assert_equal(r.area, 53120000)
assert_equal(rf.area, 53120000)
# force destroy, so the unit tests pass on the next iteration
dss._destroy
assert_equal(RBA::DeepShapeStore::instance_count, 0)
end
end
load("test_epilogue.rb")