WIP: added DeepRegion

This commit is contained in:
Matthias Koefferlein 2018-11-16 01:11:28 +01:00
parent f29fd3dfc6
commit f5cc8b6018
9 changed files with 503 additions and 19 deletions

View File

@ -139,7 +139,8 @@ SOURCES = \
dbDeepShapeStore.cc \
dbHierarchyBuilder.cc \
dbLocalOperation.cc \
dbHierProcessor.cc
dbHierProcessor.cc \
dbDeepRegion.cc
HEADERS = \
dbArray.h \

227
src/db/db/dbDeepRegion.cc Normal file
View File

@ -0,0 +1,227 @@
/*
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 "dbDeepRegion.h"
#include "dbDeepShapeStore.h"
#include "dbEmptyRegion.h"
#include "dbRegion.h"
#include "dbShapeProcessor.h"
#include "dbFlatRegion.h"
namespace db
{
// -------------------------------------------------------------------------------------------------------------
// 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))
{
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))
{
init ();
tl_assert (trans.is_unity ()); // TODO: implement
set_merged_semantics (merged_semantics);
}
DeepRegion::DeepRegion ()
: AsIfFlatRegion ()
{
init ();
}
DeepRegion::~DeepRegion ()
{
// .. nothing yet ..
}
DeepRegion::DeepRegion (const DeepRegion &other)
: AsIfFlatRegion (other),
m_deep_layer (other.m_deep_layer),
m_merged_polygons (other.m_merged_polygons),
m_merged_polygons_valid (other.m_merged_polygons_valid)
{
// .. nothing yet ..
}
void DeepRegion::init ()
{
m_merged_polygons_valid = false;
m_merged_polygons.clear ();
}
RegionDelegate *
DeepRegion::clone () const
{
return new DeepRegion (*this);
}
void DeepRegion::merged_semantics_changed ()
{
// .. nothing yet ..
}
RegionIteratorDelegate *
DeepRegion::begin () const
{
return new DeepRegionIterator (begin_iter ().first);
}
RegionIteratorDelegate *
DeepRegion::begin_merged () const
{
if (! merged_semantics ()) {
return begin ();
} else {
ensure_merged_polygons_valid ();
return new FlatRegionIterator (m_merged_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin (), m_merged_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
}
}
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
DeepRegion::begin_iter () const
{
const db::Layout *layout = m_deep_layer.layout ();
if (layout->cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
} else {
const db::Cell &top_cell = layout->cell (*layout->begin_top_down ());
db::RecursiveShapeIterator iter (*m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
}
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
DeepRegion::begin_merged_iter () const
{
if (! merged_semantics ()) {
return begin_iter ();
} else {
ensure_merged_polygons_valid ();
return std::make_pair (db::RecursiveShapeIterator (m_merged_polygons), db::ICplxTrans ());
}
}
bool
DeepRegion::empty () const
{
return begin_iter ().first.at_end ();
}
bool
DeepRegion::is_merged () const
{
return false;
}
const db::Polygon *
DeepRegion::nth (size_t) const
{
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
}
bool
DeepRegion::has_valid_polygons () const
{
return false;
}
bool
DeepRegion::has_valid_merged_polygons () const
{
return merged_semantics ();
}
const db::RecursiveShapeIterator *
DeepRegion::iter () const
{
return 0;
}
bool
DeepRegion::equals (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast<const DeepRegion *> (other.delegate ());
if (other_delegate && other_delegate->m_deep_layer.layout () == m_deep_layer.layout ()
&& other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
return true;
} else {
return AsIfFlatRegion::equals (other);
}
}
bool
DeepRegion::less (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast<const DeepRegion *> (other.delegate ());
if (other_delegate && other_delegate->m_deep_layer.layout () == m_deep_layer.layout ()) {
return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
} else {
return AsIfFlatRegion::less (other);
}
}
void
DeepRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
m_merged_polygons.clear ();
db::EdgeProcessor ep (report_progress (), progress_desc ());
// count edges and reserve memory
size_t n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
n += p->vertices ();
}
ep.reserve (n);
// insert the polygons into the processor
n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
ep.insert (*p, n);
}
// and run the merge step
db::MergeOp op (0);
db::ShapeGenerator pc (m_merged_polygons);
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence ());
ep.process (pg, op);
m_merged_polygons_valid = true;
}
}
}

141
src/db/db/dbDeepRegion.h Normal file
View File

@ -0,0 +1,141 @@
/*
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
*/
#ifndef HDR_dbDeepRegion
#define HDR_dbDeepRegion
#include "dbCommon.h"
#include "dbAsIfFlatRegion.h"
#include "dbDeepShapeStore.h"
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
*/
class DB_PUBLIC DeepRegion
: public AsIfFlatRegion
{
public:
typedef db::layer<db::Polygon, db::unstable_layer_tag> polygon_layer_type;
typedef polygon_layer_type::iterator polygon_iterator_type;
DeepRegion ();
DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio = 3.0, size_t max_vertex_count = 16);
DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true, double area_ratio = 3.0, size_t max_vertex_count = 16);
DeepRegion (const DeepRegion &other);
virtual ~DeepRegion ();
RegionDelegate *clone () const;
virtual RegionIteratorDelegate *begin () const;
virtual RegionIteratorDelegate *begin_merged () const;
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const;
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
virtual bool empty () const;
virtual bool is_merged () const;
virtual const db::Polygon *nth (size_t n) const;
virtual bool has_valid_polygons () const;
virtual bool has_valid_merged_polygons () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
protected:
virtual void merged_semantics_changed ();
private:
DeepRegion &operator= (const DeepRegion &other);
DeepLayer m_deep_layer;
// @@@ have hierarchical merged polygons later
mutable db::Shapes m_merged_polygons;
mutable bool m_merged_polygons_valid;
void init ();
void ensure_merged_polygons_valid () const;
};
}
#endif

View File

@ -22,10 +22,19 @@
#include "dbDeepShapeStore.h"
#include "tlTimer.h"
namespace db
{
// ----------------------------------------------------------------------------------
DeepLayer::DeepLayer ()
: mp_store (), m_layout (0), m_layer (0)
{
// .. nothing yet ..
}
DeepLayer::DeepLayer (const DeepLayer &x)
: mp_store (x.mp_store), m_layout (x.m_layout), m_layer (x.m_layer)
{
@ -38,21 +47,65 @@ DeepLayer::DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int l
// .. nothing yet ..
}
// ----------------------------------------------------------------------------------
DeepShapeStore::DeepShapeStore ()
{
// @@@
// .. nothing yet ..
}
DeepShapeStore::~DeepShapeStore ()
{
// @@@
// .. nothing yet ..
}
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
{
return DeepLayer (0, 0, 0); // @@@
unsigned int layout_index = 0;
unsigned int layer_index = 0;
layout_map_type::iterator l = m_layout_map.find (si);
if (l == m_layout_map.end ()) {
layout_index = (unsigned int) m_layouts.size ();
m_layouts.push_back (new db::Layout ());
m_layouts.back ().dbu (si.layout ()->dbu ());
layer_index = m_layouts.back ().insert_layer ();
m_builders.push_back (new db::HierarchyBuilder (&m_layouts.back (), layer_index));
m_layout_map[si] = layout_index;
} else {
layout_index = l->second;
layer_index = m_layouts[layout_index].insert_layer ();
m_builders[layout_index].set_target_layer (layer_index);
}
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& m_layouts[layout_index]);
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
db::ClippingHierarchyBuilderShapeReceiver clip (&red);
// Build the working hierarchy from the recursive shape iterator
try {
tl::SelfTimer timer (tl::to_string (tr ("Building working hierarchy")));
m_builders[layout_index].set_shape_receiver (&clip);
db::RecursiveShapeIterator (si).push (& m_builders[layout_index]);
m_builders[layout_index].set_shape_receiver (0);
} catch (...) {
m_builders[layout_index].set_shape_receiver (0);
throw;
}
return DeepLayer (this, layout_index, layer_index);
}
}

View File

@ -27,8 +27,10 @@
#include "dbCommon.h"
#include "tlObject.h"
#include "tlStableVector.h"
#include "dbLayout.h"
#include "dbRecursiveShapeIterator.h"
#include "dbHierarchyBuilder.h"
#include <set>
#include <map>
@ -46,6 +48,11 @@ class DeepShapeStore;
class DB_PUBLIC DeepLayer
{
public:
/**
* @brief Default constructor
*/
DeepLayer ();
/**
* @brief Destructor
*/
@ -63,11 +70,15 @@ public:
/**
* @brief Gets the layout object
*
* The return value is guaranteed to be non-null.
*/
db::Layout *layout ();
/**
* @brief Gets the layout object (const version)
*/
const db::Layout *layout () const;
/**
* @brief Gets the layer
*/
@ -89,6 +100,14 @@ private:
unsigned int m_layer;
};
struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy
{
bool operator () (const db::RecursiveShapeIterator &a, const db::RecursiveShapeIterator &b) const
{
return db::compare_iterators_with_respect_to_target_hierarchy (a, b) < 0;
}
};
/**
* @brief The "deep shape store" is a working model for the hierarchical ("deep") processor
*
@ -128,10 +147,15 @@ public:
DeepLayer create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio = 3.0, size_t max_vertex_count = 16);
private:
typedef std::map<db::RecursiveShapeIterator, unsigned int, RecursiveShapeIteratorCompareForTargetHierarchy> layout_map_type;
// no copying
DeepShapeStore (const DeepShapeStore &);
DeepShapeStore &operator= (const DeepShapeStore &);
tl::stable_vector<db::Layout> m_layouts;
tl::stable_vector<db::HierarchyBuilder> m_builders;
layout_map_type m_layout_map;
};
}

View File

@ -125,13 +125,13 @@ static std::pair<bool, std::set<db::Box> > compute_clip_variant (const db::Box &
HierarchyBuilder::HierarchyBuilder (db::Layout *target, unsigned int target_layer, HierarchyBuilderShapeReceiver *pipe)
: mp_target (target), m_initial_pass (true), m_target_layer (target_layer)
{
mp_pipe = pipe ? pipe : &def_inserter;
set_shape_receiver (pipe);
}
HierarchyBuilder::HierarchyBuilder (db::Layout *target, HierarchyBuilderShapeReceiver *pipe)
: mp_target (target), m_initial_pass (true), m_target_layer (0)
{
mp_pipe = pipe ? pipe : &def_inserter;
set_shape_receiver (pipe);
}
HierarchyBuilder::~HierarchyBuilder ()
@ -142,7 +142,7 @@ HierarchyBuilder::~HierarchyBuilder ()
void
HierarchyBuilder::set_shape_receiver (HierarchyBuilderShapeReceiver *pipe)
{
mp_pipe = pipe;
mp_pipe = pipe ? pipe : &def_inserter;
}
void
@ -191,8 +191,9 @@ HierarchyBuilder::end (const RecursiveShapeIterator * /*iter*/)
m_initial_pass = false;
m_cells_seen.clear ();
mp_initial_cell = m_cell_stack.back ();
m_cell_stack.pop_back ();
mp_initial_cell = m_cell_stack.front ();
m_cell_stack.clear ();
m_cm_entry = cell_map_type::const_iterator ();
}
void

View File

@ -961,14 +961,23 @@ RecursiveShapeIterator::push (RecursiveShapeReceiver *receiver)
receiver->begin (this);
validate (receiver);
try {
validate (receiver);
while (! at_end ()) {
receiver->shape (this, *m_shape, m_trans, m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
next (receiver);
}
receiver->end (this);
} catch (...) {
receiver->end (this);
throw;
while (! at_end ()) {
receiver->shape (this, *m_shape, m_trans, m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
next (receiver);
}
receiver->end (this);
}
}

View File

@ -25,6 +25,7 @@
#include "dbOriginalLayerRegion.h"
#include "dbEmptyRegion.h"
#include "dbFlatRegion.h"
#include "dbDeepRegion.h"
namespace db
{
@ -74,6 +75,16 @@ Region::Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, b
mp_delegate = new OriginalLayerRegion (si, trans, merged_semantics);
}
Region::Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
{
mp_delegate = new DeepRegion (si, dss, area_ratio, max_vertex_count);
}
Region::Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics, double area_ratio, size_t max_vertex_count)
{
mp_delegate = new DeepRegion (si, dss, trans, merged_semantics, area_ratio, max_vertex_count);
}
const db::RecursiveShapeIterator &
Region::iter () const
{

View File

@ -38,6 +38,7 @@ namespace db {
class EdgeFilterBase;
class FlatRegion;
class EmptyRegion;
class DeepShapeStore;
/**
* @brief A base class for polygon filters
@ -532,7 +533,7 @@ public:
/**
* @brief Constructor from a RecursiveShapeIterator
*
* Creates a region from a recursive shape iterator. This allows to feed a region
* Creates a region from a recursive shape iterator. This allows feeding a region
* from a hierarchy of cells.
*/
Region (const RecursiveShapeIterator &si);
@ -540,12 +541,28 @@ public:
/**
* @brief Constructor from a RecursiveShapeIterator with a transformation
*
* Creates a region from a recursive shape iterator. This allows to feed a region
* Creates a region from a recursive shape iterator. This allows feeding a region
* from a hierarchy of cells. The transformation is useful to scale to a specific
* DBU for example.
*/
Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics = true);
/**
* @brief Constructor from a RecursiveShapeIterator providing a deep representation
*
* This version will create a hierarchical region. The DeepShapeStore needs to be provided
* during the lifetime of the region and acts as a heap for optimized data.
*
* "area_ratio" and "max_vertex_count" are optimization parameters for the
* shape splitting algorithm.
*/
Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio = 3.0, size_t max_vertex_count = 16);
/**
* @brief Constructor from a RecursiveShapeIterator providing a deep representation with transformation
*/
Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true, double area_ratio = 3.0, size_t max_vertex_count = 16);
/**
* @brief Gets the underlying delegate object
*/