mirror of https://github.com/KLayout/klayout.git
WIP: local hierarchical operations: take boolean core rather than shape ref core -> better hierarchical quality. Tests need to be fixed.
This commit is contained in:
parent
a635435899
commit
707c761bac
|
|
@ -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") {
|
||||
|
||||
|
|
|
|||
|
|
@ -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<db::PolygonRef> &res, const std::unordered_set<db::PolygonRef> &other, db::Layout *layout)
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
for (std::unordered_set<db::PolygonRef>::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<db::PolygonRef>::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<db::PolygonRef> new_common;
|
||||
for (std::unordered_set<db::PolygonRef>::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<key_type, db::LocalProcessorCellContext>::iterator cc = m_contexts.begin (); cc != c; ++cc) {
|
||||
cc->second.propagate (lost);
|
||||
if (! lost.empty ()) {
|
||||
subtract (common, lost, cell->layout ());
|
||||
for (std::unordered_map<key_type, db::LocalProcessorCellContext>::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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<db::PolygonRef> &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<db::PolygonRef> *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 <db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
for (std::vector <db::Polygon>::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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<db::PolygonRef> &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 <db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
for (std::vector <db::Polygon>::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) {
|
||||
put (*sp);
|
||||
}
|
||||
|
||||
} else {
|
||||
mp_sink->put (poly);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <unordered_set>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class PolygonRefGenerator
|
||||
: public PolygonSink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor specifying an external vector for storing the polygons
|
||||
*/
|
||||
PolygonRefGenerator (db::Layout *layout, std::unordered_set<db::PolygonRef> &polyrefs);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Polygon &polygon);
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::unordered_set<db::PolygonRef> *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
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue