mirror of https://github.com/KLayout/klayout.git
WIP: deep region debugged, GSI binding, tests.
This commit is contained in:
parent
f5cc8b6018
commit
a438dfd6f0
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ®ion)
|
||||
{
|
||||
region.insert_into (this, cell, layer);
|
||||
}
|
||||
|
||||
void
|
||||
Layout::flatten (const db::Cell &source_cell, db::Cell &target_cell, const db::ICplxTrans &t, int levels)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ®ion);
|
||||
|
||||
/**
|
||||
* @brief Delete a cell plus all subcells
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue