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
|
bool
|
||||||
AsIfFlatRegion::equals (const Region &other) const
|
AsIfFlatRegion::equals (const Region &other) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,8 @@ public:
|
||||||
virtual bool equals (const Region &other) const;
|
virtual bool equals (const Region &other) const;
|
||||||
virtual bool less (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:
|
protected:
|
||||||
void update_bbox (const db::Box &box);
|
void update_bbox (const db::Box &box);
|
||||||
void invalidate_bbox ();
|
void invalidate_bbox ();
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,17 @@ public:
|
||||||
return m_b2a_mapping;
|
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:
|
private:
|
||||||
void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand,
|
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,
|
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,
|
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);
|
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;
|
std::map <db::cell_index_type, db::cell_index_type> m_b2a_mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,73 @@
|
||||||
namespace db
|
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 implementation
|
||||||
|
|
||||||
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
|
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 ();
|
init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics, double area_ratio, size_t max_vertex_count)
|
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 ();
|
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 {
|
namespace db {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An iterator delegate for the deep region
|
* @brief A deep, polygon-set delegate
|
||||||
*/
|
|
||||||
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
|
|
||||||
*/
|
*/
|
||||||
class DB_PUBLIC DeepRegion
|
class DB_PUBLIC DeepRegion
|
||||||
: public AsIfFlatRegion
|
: public AsIfFlatRegion
|
||||||
|
|
@ -120,6 +70,8 @@ public:
|
||||||
virtual bool equals (const Region &other) const;
|
virtual bool equals (const Region &other) const;
|
||||||
virtual bool less (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:
|
protected:
|
||||||
virtual void merged_semantics_changed ();
|
virtual void merged_semantics_changed ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
|
|
||||||
#include "dbDeepShapeStore.h"
|
#include "dbDeepShapeStore.h"
|
||||||
|
#include "dbCellMapping.h"
|
||||||
|
#include "dbLayoutUtils.h"
|
||||||
|
|
||||||
#include "tlTimer.h"
|
#include "tlTimer.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
|
|
@ -47,16 +50,57 @@ DeepLayer::DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int l
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
DeepLayer::~DeepLayer ()
|
||||||
|
|
||||||
DeepShapeStore::DeepShapeStore ()
|
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. 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 ()
|
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)
|
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);
|
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 "dbLayout.h"
|
||||||
#include "dbRecursiveShapeIterator.h"
|
#include "dbRecursiveShapeIterator.h"
|
||||||
#include "dbHierarchyBuilder.h"
|
#include "dbHierarchyBuilder.h"
|
||||||
|
#include "gsiObject.h"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
@ -87,6 +88,19 @@ public:
|
||||||
return m_layer;
|
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:
|
private:
|
||||||
friend class DeepShapeStore;
|
friend class DeepShapeStore;
|
||||||
|
|
||||||
|
|
@ -95,6 +109,8 @@ private:
|
||||||
*/
|
*/
|
||||||
DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int layer);
|
DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int layer);
|
||||||
|
|
||||||
|
void check_dss () const;
|
||||||
|
|
||||||
tl::weak_ptr<DeepShapeStore> mp_store;
|
tl::weak_ptr<DeepShapeStore> mp_store;
|
||||||
unsigned int m_layout;
|
unsigned int m_layout;
|
||||||
unsigned int m_layer;
|
unsigned int m_layer;
|
||||||
|
|
@ -121,7 +137,7 @@ struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy
|
||||||
* algorithms for doing the preparation and transfer.
|
* algorithms for doing the preparation and transfer.
|
||||||
*/
|
*/
|
||||||
class DB_PUBLIC DeepShapeStore
|
class DB_PUBLIC DeepShapeStore
|
||||||
: public tl::Object
|
: public tl::Object, public gsi::ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
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);
|
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:
|
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;
|
typedef std::map<db::RecursiveShapeIterator, unsigned int, RecursiveShapeIteratorCompareForTargetHierarchy> layout_map_type;
|
||||||
|
|
||||||
// no copying
|
// no copying
|
||||||
|
|
@ -156,9 +189,47 @@ private:
|
||||||
tl::stable_vector<db::Layout> m_layouts;
|
tl::stable_vector<db::Layout> m_layouts;
|
||||||
tl::stable_vector<db::HierarchyBuilder> m_builders;
|
tl::stable_vector<db::HierarchyBuilder> m_builders;
|
||||||
layout_map_type m_layout_map;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,8 @@ public:
|
||||||
virtual bool equals (const Region &other) const;
|
virtual bool equals (const Region &other) const;
|
||||||
virtual bool less (const Region &other) const;
|
virtual bool less (const Region &other) const;
|
||||||
|
|
||||||
|
virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EmptyRegion &operator= (const EmptyRegion &other);
|
EmptyRegion &operator= (const EmptyRegion &other);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -362,6 +362,11 @@ const db::RecursiveShapeIterator *FlatRegion::iter () const
|
||||||
return 0;
|
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
|
void
|
||||||
FlatRegion::insert (const db::Box &box)
|
FlatRegion::insert (const db::Box &box)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ public:
|
||||||
virtual size_t size () const;
|
virtual size_t size () const;
|
||||||
virtual bool is_merged () 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 ();
|
||||||
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc);
|
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc);
|
||||||
virtual RegionDelegate *merged () const;
|
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 ()) {
|
if (iter1.has_complex_region () && iter1.complex_region () != iter2.complex_region ()) {
|
||||||
return iter1.complex_region () < iter2.complex_region () ? -1 : 1;
|
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 ()) {
|
if (iter1.multiple_layers () != iter2.multiple_layers ()) {
|
||||||
return iter1.multiple_layers () < iter2.multiple_layers () ? -1 : 1;
|
return iter1.multiple_layers () < iter2.multiple_layers () ? -1 : 1;
|
||||||
}
|
}
|
||||||
if (iter1.multiple_layers ()) {
|
if (iter1.multiple_layers ()) {
|
||||||
if (iter1.layers () != iter2.layers ()) {
|
if (iter1.layers () != iter2.layers ()) {
|
||||||
return iter1.layers () < iter2.layers ();
|
return iter1.layers () < iter2.layers () ? -1 : 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (iter1.layer () != iter2.layer ()) {
|
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)
|
HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
|
||||||
{
|
{
|
||||||
if (m_initial_pass) {
|
if (m_initial_pass) {
|
||||||
m_ref_iter = *iter;
|
m_source = *iter;
|
||||||
} else {
|
} 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 ();
|
m_cell_stack.clear ();
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace db
|
||||||
* This function will return -1, 0 or 1 depending on whether the two iterators
|
* 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).
|
* 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
|
* @brief A class to receive shapes from the hierarchy builder
|
||||||
|
|
@ -199,18 +199,50 @@ public:
|
||||||
void reset ();
|
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 ()
|
db::Cell *initial_cell ()
|
||||||
{
|
{
|
||||||
return mp_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:
|
private:
|
||||||
tl::weak_ptr<db::Layout> mp_target;
|
tl::weak_ptr<db::Layout> mp_target;
|
||||||
HierarchyBuilderShapeReceiver *mp_pipe;
|
HierarchyBuilderShapeReceiver *mp_pipe;
|
||||||
bool m_initial_pass;
|
bool m_initial_pass;
|
||||||
db::RecursiveShapeIterator m_ref_iter;
|
db::RecursiveShapeIterator m_source;
|
||||||
cell_map_type m_cell_map;
|
cell_map_type m_cell_map;
|
||||||
std::set<cell_map_type::key_type> m_cells_seen;
|
std::set<cell_map_type::key_type> m_cells_seen;
|
||||||
cell_map_type::const_iterator m_cm_entry;
|
cell_map_type::const_iterator m_cm_entry;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "dbLibraryProxy.h"
|
#include "dbLibraryProxy.h"
|
||||||
#include "dbLibraryManager.h"
|
#include "dbLibraryManager.h"
|
||||||
#include "dbLibrary.h"
|
#include "dbLibrary.h"
|
||||||
|
#include "dbRegion.h"
|
||||||
#include "tlTimer.h"
|
#include "tlTimer.h"
|
||||||
#include "tlLog.h"
|
#include "tlLog.h"
|
||||||
#include "tlInternational.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
|
void
|
||||||
Layout::flatten (const db::Cell &source_cell, db::Cell &target_cell, const db::ICplxTrans &t, int levels)
|
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 LibraryProxy;
|
||||||
class CellMapping;
|
class CellMapping;
|
||||||
class LayerMapping;
|
class LayerMapping;
|
||||||
|
class Region;
|
||||||
|
|
||||||
template <class Coord> class generic_repository;
|
template <class Coord> class generic_repository;
|
||||||
typedef generic_repository<db::Coord> GenericRepository;
|
typedef generic_repository<db::Coord> GenericRepository;
|
||||||
|
|
@ -1090,6 +1091,15 @@ public:
|
||||||
*/
|
*/
|
||||||
void flatten (db::Cell &cell, int levels, bool prune = false);
|
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
|
* @brief Delete a cell plus all subcells
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1685,6 +1685,14 @@ public:
|
||||||
return mp_delegate->less (other);
|
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:
|
private:
|
||||||
friend class Edges;
|
friend class Edges;
|
||||||
friend class EdgePairs;
|
friend class EdgePairs;
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,8 @@ public:
|
||||||
virtual bool equals (const Region &other) const = 0;
|
virtual bool equals (const Region &other) const = 0;
|
||||||
virtual bool less (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:
|
protected:
|
||||||
const std::string &progress_desc () const
|
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")));
|
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::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||||
|
|
||||||
db::CellMapping cm;
|
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")));
|
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::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||||
|
|
||||||
db::LayerMapping lm;
|
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")));
|
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::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||||
|
|
||||||
std::vector <db::cell_index_type> source_cells;
|
std::vector <db::cell_index_type> source_cells;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "dbLibraryManager.h"
|
#include "dbLibraryManager.h"
|
||||||
#include "dbPCellDeclaration.h"
|
#include "dbPCellDeclaration.h"
|
||||||
#include "dbHash.h"
|
#include "dbHash.h"
|
||||||
|
#include "dbRegion.h"
|
||||||
#include "tlStream.h"
|
#include "tlStream.h"
|
||||||
|
|
||||||
namespace gsi
|
namespace gsi
|
||||||
|
|
@ -1179,6 +1180,18 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.20.\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,
|
gsi::method_ext ("flatten", &flatten,
|
||||||
"@brief Flattens the given cell\n"
|
"@brief Flattens the given cell\n"
|
||||||
"@args cell_index, levels, prune\n"
|
"@args cell_index, levels, prune\n"
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
#include "dbPolygonTools.h"
|
#include "dbPolygonTools.h"
|
||||||
#include "dbLayoutUtils.h"
|
#include "dbLayoutUtils.h"
|
||||||
#include "dbShapes.h"
|
#include "dbShapes.h"
|
||||||
|
#include "dbDeepShapeStore.h"
|
||||||
|
#include "dbRegion.h"
|
||||||
#include "tlGlobPattern.h"
|
#include "tlGlobPattern.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -213,6 +215,11 @@ static db::Region *new_si (const db::RecursiveShapeIterator &si)
|
||||||
return new db::Region (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)
|
static db::Region *new_si2 (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
|
||||||
{
|
{
|
||||||
return new db::Region (si, 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 td_simple ();
|
||||||
int po_any ();
|
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",
|
Class<db::Region> decl_Region ("db", "Region",
|
||||||
constructor ("new", &new_v,
|
constructor ("new", &new_v,
|
||||||
"@brief Default constructor\n"
|
"@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"
|
"r = RBA::Region::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n"
|
||||||
"@/code\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),
|
constructor ("new", &new_texts<BoxDelivery>, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true),
|
||||||
"@brief Constructor from a text set\n"
|
"@brief Constructor from a text set\n"
|
||||||
"\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");
|
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 \
|
dbSaveLayoutOptionsTests.cc \
|
||||||
dbHierarchyBuilderTests.cc \
|
dbHierarchyBuilderTests.cc \
|
||||||
dbRecursiveShapeIteratorTests.cc \
|
dbRecursiveShapeIteratorTests.cc \
|
||||||
dbHierProcessorTests.cc
|
dbHierProcessorTests.cc \
|
||||||
|
dbDeepRegionTests.cc
|
||||||
|
|
||||||
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
|
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||||
DEPENDPATH += $$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
|
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
|
end
|
||||||
|
|
||||||
load("test_epilogue.rb")
|
load("test_epilogue.rb")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue