From f5cc8b6018d75bd50dfc63072f92090d2a9b9616 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 16 Nov 2018 01:11:28 +0100 Subject: [PATCH] WIP: added DeepRegion --- src/db/db/db.pro | 3 +- src/db/db/dbDeepRegion.cc | 227 ++++++++++++++++++++++++++ src/db/db/dbDeepRegion.h | 141 ++++++++++++++++ src/db/db/dbDeepShapeStore.cc | 61 ++++++- src/db/db/dbDeepShapeStore.h | 26 ++- src/db/db/dbHierarchyBuilder.cc | 11 +- src/db/db/dbRecursiveShapeIterator.cc | 21 ++- src/db/db/dbRegion.cc | 11 ++ src/db/db/dbRegion.h | 21 ++- 9 files changed, 503 insertions(+), 19 deletions(-) create mode 100644 src/db/db/dbDeepRegion.cc create mode 100644 src/db/db/dbDeepRegion.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index c0b0d45c6..7d2d2d563 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -139,7 +139,8 @@ SOURCES = \ dbDeepShapeStore.cc \ dbHierarchyBuilder.cc \ dbLocalOperation.cc \ - dbHierProcessor.cc + dbHierProcessor.cc \ + dbDeepRegion.cc HEADERS = \ dbArray.h \ diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc new file mode 100644 index 000000000..78fa48d95 --- /dev/null +++ b/src/db/db/dbDeepRegion.cc @@ -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 ().begin (), m_merged_polygons.get_layer ().end ()); + } +} + +std::pair +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 +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 (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 (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; + + } +} + +} + diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h new file mode 100644 index 000000000..415973bf8 --- /dev/null +++ b/src/db/db/dbDeepRegion.h @@ -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 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 begin_iter () const; + virtual std::pair 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 + diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index abb1469e8..e9a317ae9 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -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); } } diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index f76805fd1..c08bfb44d 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -27,8 +27,10 @@ #include "dbCommon.h" #include "tlObject.h" +#include "tlStableVector.h" #include "dbLayout.h" #include "dbRecursiveShapeIterator.h" +#include "dbHierarchyBuilder.h" #include #include @@ -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 layout_map_type; + // no copying DeepShapeStore (const DeepShapeStore &); DeepShapeStore &operator= (const DeepShapeStore &); + tl::stable_vector m_layouts; + tl::stable_vector m_builders; + layout_map_type m_layout_map; }; } diff --git a/src/db/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc index be5945412..383f2b685 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -125,13 +125,13 @@ static std::pair > 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 diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index d55bce34c..18173f2ff 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -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); } } diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index 74f8039c5..b9ced87ec 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -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 { diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index c0772dc89..4a4cc4e9e 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -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 */