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:
Matthias Koefferlein 2019-01-25 00:21:01 +01:00
parent a635435899
commit 707c761bac
6 changed files with 227 additions and 78 deletions

View File

@ -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") {

View File

@ -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);
}
}
}

View File

@ -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)
{

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}