From 707c761bacff8aa063f99d19da60b79f05218c38 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 25 Jan 2019 00:21:01 +0100 Subject: [PATCH] WIP: local hierarchical operations: take boolean core rather than shape ref core -> better hierarchical quality. Tests need to be fixed. --- src/db/db/db.pro | 6 +- src/db/db/dbHierProcessor.cc | 63 +++++++++++++++--- src/db/db/dbLocalOperation.cc | 67 +------------------ src/db/db/dbLocalOperationUtils.cc | 70 ++++++++++++++++++++ src/db/db/dbLocalOperationUtils.h | 78 +++++++++++++++++++++++ src/db/unit_tests/dbHierProcessorTests.cc | 21 ++++++ 6 files changed, 227 insertions(+), 78 deletions(-) create mode 100644 src/db/db/dbLocalOperationUtils.cc create mode 100644 src/db/db/dbLocalOperationUtils.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 0c9fcd68f..3a99dcb25 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -162,7 +162,8 @@ SOURCES = \ dbLayoutToNetlistReader.cc \ dbLayoutToNetlistWriter.cc \ dbLayoutToNetlistFormatDefs.cc \ - dbDeviceAbstract.cc + dbDeviceAbstract.cc \ + dbLocalOperationUtils.cc HEADERS = \ dbArray.h \ @@ -289,7 +290,8 @@ HEADERS = \ dbLayoutToNetlistReader.h \ dbLayoutToNetlistWriter.h \ dbLayoutToNetlistFormatDefs.h \ - dbDeviceAbstract.h + dbDeviceAbstract.h \ + dbLocalOperationUtils.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 537d52967..4e652c26b 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -27,6 +27,7 @@ #include "dbBoxConvert.h" #include "dbEdgeProcessor.h" #include "dbPolygonGenerators.h" +#include "dbLocalOperationUtils.h" #include "tlLog.h" #include "tlTimer.h" #include "tlInternational.h" @@ -253,6 +254,43 @@ LocalProcessorCellContexts::create (const key_type &intruders) return &m_contexts[intruders]; } +static void +subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout *layout) +{ + if (other.empty ()) { + return; + } + + db::EdgeProcessor ep; + + size_t p1 = 0, p2 = 1; + + for (std::unordered_set::const_iterator i = res.begin (); i != res.end (); ++i) { + const db::PolygonRef &subject = *i; + for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) { + ep.insert (*e, p1); + } + p1 += 2; + } + + for (std::unordered_set::const_iterator i = other.begin (); i != other.end (); ++i) { + const db::PolygonRef &subject = *i; + for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) { + ep.insert (*e, p2); + } + p2 += 2; + } + + double m_max_area_ratio = 3.0; // @@@ + size_t m_max_vertex_count = 16; // @@@ + res.clear (); + db::BooleanOp op (db::BooleanOp::ANotB); + db::PolygonRefGenerator pr (layout, res); + db::PolygonSplitter splitter (pr, m_max_area_ratio, m_max_vertex_count); + db::PolygonGenerator pg (splitter, true, true); + ep.process (pg, op); +} + void LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, unsigned int output_layer, const LocalProcessor *proc) { @@ -313,16 +351,13 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte if (! lost.empty ()) { - std::unordered_set new_common; - for (std::unordered_set::const_iterator i = common.begin (); i != common.end (); ++i) { - if (res.find (*i) != res.end ()) { - new_common.insert (*i); - } - } - common.swap (new_common); + subtract (lost, res, cell->layout ()); - for (std::unordered_map::iterator cc = m_contexts.begin (); cc != c; ++cc) { - cc->second.propagate (lost); + if (! lost.empty ()) { + subtract (common, lost, cell->layout ()); + for (std::unordered_map::iterator cc = m_contexts.begin (); cc != c; ++cc) { + cc->second.propagate (lost); + } } } @@ -334,7 +369,15 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte } } - c->second.propagate (gained); + if (! gained.empty ()) { + + subtract (gained, common, cell->layout ()); + + if (! gained.empty ()) { + c->second.propagate (gained); + } + + } } diff --git a/src/db/db/dbLocalOperation.cc b/src/db/db/dbLocalOperation.cc index acedde581..362a80caa 100644 --- a/src/db/db/dbLocalOperation.cc +++ b/src/db/db/dbLocalOperation.cc @@ -28,6 +28,7 @@ #include "dbEdgeProcessor.h" #include "dbPolygonGenerators.h" #include "dbPolygonTools.h" +#include "dbLocalOperationUtils.h" #include "tlLog.h" #include "tlTimer.h" #include "tlInternational.h" @@ -35,75 +36,9 @@ namespace db { - // --------------------------------------------------------------------------------------------- // BoolAndOrNotLocalOperation implementation -namespace { - -class PolygonRefGenerator - : public PolygonSink -{ -public: - /** - * @brief Constructor specifying an external vector for storing the polygons - */ - PolygonRefGenerator (db::Layout *layout, std::unordered_set &polyrefs) - : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs) - { } - - /** - * @brief Implementation of the PolygonSink interface - */ - virtual void put (const db::Polygon &polygon) - { - tl::MutexLocker locker (&mp_layout->lock ()); - mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ())); - } - -private: - db::Layout *mp_layout; - std::unordered_set *mp_polyrefs; -}; - -class PolygonSplitter - : public PolygonSink -{ -public: - PolygonSplitter (PolygonSink &sink, double max_area_ratio, size_t max_vertex_count) - : mp_sink (&sink), m_max_area_ratio (max_area_ratio), m_max_vertex_count (max_vertex_count) - { - // .. nothing yet .. - } - - virtual void put (const db::Polygon &poly) - { - if ((m_max_vertex_count > 0 && poly.vertices () > m_max_vertex_count) || (m_max_area_ratio > 0.0 && poly.area_ratio () > m_max_area_ratio)) { - - std::vector split_polygons; - db::split_polygon (poly, split_polygons); - for (std::vector ::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) { - put (*sp); - } - - } else { - mp_sink->put (poly); - } - } - - virtual void start () { mp_sink->start (); } - virtual void flush () { mp_sink->flush (); } - -private: - PolygonSink *mp_sink; - double m_max_area_ratio; - size_t m_max_vertex_count; -}; - -} - -// --------------------------------------------------------------------------------------------- - BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and, double max_area_ratio, size_t max_vertex_count) : m_is_and (is_and), m_max_area_ratio (max_area_ratio), m_max_vertex_count (max_vertex_count) { diff --git a/src/db/db/dbLocalOperationUtils.cc b/src/db/db/dbLocalOperationUtils.cc new file mode 100644 index 000000000..04fe0c747 --- /dev/null +++ b/src/db/db/dbLocalOperationUtils.cc @@ -0,0 +1,70 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2019 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 "dbLocalOperationUtils.h" +#include "dbPolygonTools.h" + +namespace db +{ + +// ----------------------------------------------------------------------------------------------- +// class PolygonRefGenerator + +PolygonRefGenerator::PolygonRefGenerator (db::Layout *layout, std::unordered_set &polyrefs) + : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs) +{ + // .. nothing yet .. +} + +void PolygonRefGenerator::put (const db::Polygon &polygon) +{ + tl::MutexLocker locker (&mp_layout->lock ()); + mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ())); +} + +// ----------------------------------------------------------------------------------------------- +// class PolygonSplitter + +PolygonSplitter::PolygonSplitter (PolygonSink &sink, double max_area_ratio, size_t max_vertex_count) + : mp_sink (&sink), m_max_area_ratio (max_area_ratio), m_max_vertex_count (max_vertex_count) +{ + // .. nothing yet .. +} + +void +PolygonSplitter::put (const db::Polygon &poly) +{ + if ((m_max_vertex_count > 0 && poly.vertices () > m_max_vertex_count) || (m_max_area_ratio > 0.0 && poly.area_ratio () > m_max_area_ratio)) { + + std::vector split_polygons; + db::split_polygon (poly, split_polygons); + for (std::vector ::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) { + put (*sp); + } + + } else { + mp_sink->put (poly); + } +} + +} diff --git a/src/db/db/dbLocalOperationUtils.h b/src/db/db/dbLocalOperationUtils.h new file mode 100644 index 000000000..ddcfa4ecc --- /dev/null +++ b/src/db/db/dbLocalOperationUtils.h @@ -0,0 +1,78 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2019 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_dbLocalOperationUtils +#define HDR_dbLocalOperationUtils + +#include "dbCommon.h" + +#include "dbLayout.h" +#include "dbPolygonGenerators.h" +#include "dbHash.h" + +#include + +namespace db +{ + +class PolygonRefGenerator + : public PolygonSink +{ +public: + /** + * @brief Constructor specifying an external vector for storing the polygons + */ + PolygonRefGenerator (db::Layout *layout, std::unordered_set &polyrefs); + + /** + * @brief Implementation of the PolygonSink interface + */ + virtual void put (const db::Polygon &polygon); + +private: + db::Layout *mp_layout; + std::unordered_set *mp_polyrefs; +}; + +class PolygonSplitter + : public PolygonSink +{ +public: + PolygonSplitter (PolygonSink &sink, double max_area_ratio, size_t max_vertex_count); + + virtual void put (const db::Polygon &poly); + + virtual void start () { mp_sink->start (); } + virtual void flush () { mp_sink->flush (); } + +private: + PolygonSink *mp_sink; + double m_max_area_ratio; + size_t m_max_vertex_count; +}; + +} + +#endif + diff --git a/src/db/unit_tests/dbHierProcessorTests.cc b/src/db/unit_tests/dbHierProcessorTests.cc index a457db90d..217acfc6b 100644 --- a/src/db/unit_tests/dbHierProcessorTests.cc +++ b/src/db/unit_tests/dbHierProcessorTests.cc @@ -1070,3 +1070,24 @@ TEST(TopWithBelow2) { run_test_bool (_this, "hlp12.oas", TMNotSwapped, 101); } + +TEST(BasicHierarchyVariantsAnd) +{ + run_test_bool (_this, "hlp13.oas", TMAnd, 100); +} + +TEST(BasicHierarchyVariantsNot) +{ + run_test_bool (_this, "hlp13.oas", TMNot, 101); +} + +TEST(BasicHierarchyVariantsAnd2) +{ + run_test_bool (_this, "hlp14.oas", TMAnd, 100); +} + +TEST(BasicHierarchyVariantsNot2) +{ + run_test_bool (_this, "hlp14.oas", TMNot, 101); +} +