Some optimization: keep merged state in deep region.

This commit is contained in:
Matthias Koefferlein 2019-02-13 17:17:03 +01:00
parent 68947bedd2
commit ddcfda8761
8 changed files with 168 additions and 58 deletions

View File

@ -122,7 +122,8 @@ DeepEdges::~DeepEdges ()
DeepEdges::DeepEdges (const DeepEdges &other)
: AsIfFlatEdges (other),
m_deep_layer (other.m_deep_layer.copy ()),
m_merged_edges_valid (other.m_merged_edges_valid)
m_merged_edges_valid (other.m_merged_edges_valid),
m_is_merged (other.m_is_merged)
{
if (m_merged_edges_valid) {
m_merged_edges = other.m_merged_edges;
@ -133,6 +134,7 @@ void DeepEdges::init ()
{
m_merged_edges_valid = false;
m_merged_edges = db::DeepLayer ();
m_is_merged = false;
}
EdgesDelegate *
@ -215,8 +217,7 @@ DeepEdges::empty () const
bool
DeepEdges::is_merged () const
{
// TODO: there is no such thing as a "surely merged" state except after merged() maybe
return false;
return m_is_merged;
}
const db::Edge *
@ -354,35 +355,44 @@ DeepEdges::ensure_merged_edges_valid () const
{
if (! m_merged_edges_valid) {
m_merged_edges = m_deep_layer.derived ();
if (m_is_merged) {
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
// NOTE: this will reuse the deep layer reference
m_merged_edges = m_deep_layer;
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
} else {
db::hier_clusters<db::Edge> hc;
db::Connectivity conn;
conn.connect (m_deep_layer);
// TODO: this uses the wrong verbosity inside ...
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Edges, conn);
m_merged_edges = m_deep_layer.derived ();
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
ClusterMerger cm (m_deep_layer.layer (), hc, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity ());
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::Edge> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::Edge>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index ());
c->shapes (m_merged_edges.layer ()).insert (s);
s.clear (); // not needed anymore
db::hier_clusters<db::Edge> hc;
db::Connectivity conn;
conn.connect (m_deep_layer);
// TODO: this uses the wrong verbosity inside ...
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Edges, conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
ClusterMerger cm (m_deep_layer.layer (), hc, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity ());
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::Edge> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::Edge>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index ());
c->shapes (m_merged_edges.layer ()).insert (s);
s.clear (); // not needed anymore
}
}
}
}
m_merged_edges_valid = true;
@ -390,6 +400,13 @@ DeepEdges::ensure_merged_edges_valid () const
}
}
void
DeepEdges::set_is_merged (bool f)
{
m_is_merged = f;
m_merged_edges_valid = false;
}
void
DeepEdges::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
@ -485,8 +502,7 @@ EdgesDelegate *DeepEdges::merged () const
c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_edges.layer ());
}
res->deep_layer ().layer ();
res->set_is_merged (true);
return res.release ();
}
@ -549,6 +565,7 @@ DeepEdges::add_in_place (const Edges &other)
}
set_is_merged (false);
return this;
}

View File

@ -155,13 +155,17 @@ public:
protected:
virtual void merged_semantics_changed ();
void set_is_merged (bool f);
private:
friend class DeepRegion;
DeepEdges &operator= (const DeepEdges &other);
DeepLayer m_deep_layer;
mutable DeepLayer m_merged_edges;
mutable bool m_merged_edges_valid;
bool m_is_merged;
void init ();
void ensure_merged_edges_valid () const;

View File

@ -133,7 +133,8 @@ DeepRegion::~DeepRegion ()
DeepRegion::DeepRegion (const DeepRegion &other)
: AsIfFlatRegion (other),
m_deep_layer (other.m_deep_layer.copy ()),
m_merged_polygons_valid (other.m_merged_polygons_valid)
m_merged_polygons_valid (other.m_merged_polygons_valid),
m_is_merged (other.m_is_merged)
{
if (m_merged_polygons_valid) {
m_merged_polygons = other.m_merged_polygons;
@ -144,6 +145,7 @@ void DeepRegion::init ()
{
m_merged_polygons_valid = false;
m_merged_polygons = db::DeepLayer ();
m_is_merged = false;
}
RegionDelegate *
@ -226,8 +228,7 @@ DeepRegion::empty () const
bool
DeepRegion::is_merged () const
{
// TODO: there is no such thing as a "surely merged" state except after merged() maybe
return false;
return m_is_merged;
}
const db::Polygon *
@ -368,35 +369,44 @@ DeepRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
m_merged_polygons = m_deep_layer.derived ();
if (m_is_merged) {
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
// NOTE: this will reuse the deep layer reference
m_merged_polygons = m_deep_layer;
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
} else {
db::hier_clusters<db::PolygonRef> hc;
db::Connectivity conn;
conn.connect (m_deep_layer);
// TODO: this uses the wrong verbosity inside ...
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
m_merged_polygons = m_deep_layer.derived ();
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
ClusterMerger cm (m_deep_layer.layer (), layout, hc, min_coherence (), report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity ());
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::PolygonRef> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::PolygonRef>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index ());
c->shapes (m_merged_polygons.layer ()).insert (s);
s.clear (); // not needed anymore
db::hier_clusters<db::PolygonRef> hc;
db::Connectivity conn;
conn.connect (m_deep_layer);
// TODO: this uses the wrong verbosity inside ...
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
ClusterMerger cm (m_deep_layer.layer (), layout, hc, min_coherence (), report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity ());
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::PolygonRef> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::PolygonRef>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index ());
c->shapes (m_merged_polygons.layer ()).insert (s);
s.clear (); // not needed anymore
}
}
}
}
m_merged_polygons_valid = true;
@ -404,6 +414,13 @@ DeepRegion::ensure_merged_polygons_valid () const
}
}
void
DeepRegion::set_is_merged (bool f)
{
m_is_merged = f;
m_merged_polygons_valid = false;
}
void
DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
@ -530,6 +547,7 @@ DeepRegion::add_in_place (const Region &other)
}
set_is_merged (false);
return this;
}
@ -785,9 +803,17 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
}
res->set_is_merged (true);
return db::Edges (res.release ());
}
RegionDelegate *
DeepRegion::filter_in_place (const PolygonFilterBase &filter)
{
// TODO: implement to be really in-place
return filtered (filter);
}
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
{
@ -828,6 +854,7 @@ DeepRegion::filtered (const PolygonFilterBase &filter) const
}
res->set_is_merged (true);
return res.release ();
}
@ -839,6 +866,7 @@ DeepRegion::merged_in_place ()
// NOTE: this makes both layers share the same resource
m_deep_layer = m_merged_polygons;
set_is_merged (true);
return this;
}
@ -863,6 +891,7 @@ DeepRegion::merged () const
res->deep_layer ().layer ();
res->set_is_merged (true);
return res.release ();
}
@ -915,6 +944,12 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
}
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
// overlap after size and are not necessarily merged)
if (d < 0) {
res->set_is_merged (true);
}
return res.release ();
}
@ -989,6 +1024,12 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
}
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
// overlap after size and are not necessarily merged)
if (dx < 0 && dy < 0) {
res->set_is_merged (true);
}
return res.release ();
}
@ -1022,6 +1063,7 @@ DeepRegion::holes () const
}
res->set_is_merged (true);
return res.release ();
}
@ -1053,6 +1095,7 @@ DeepRegion::hulls () const
}
res->set_is_merged (true);
return res.release ();
}
@ -1250,7 +1293,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (m_deep_layer.store ()->threads ());
#if 0
#if defined(SPLIT )
// with these settings, the resulting polygons are broken again ...
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
@ -1258,8 +1301,9 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
proc.run (&op, m_merged_polygons.layer (), other_deep->merged_deep_layer ().layer (), dl_out.layer ());
// TODO: mark the results as merged (unless we split - see above)
return new db::DeepRegion (dl_out);
db::DeepRegion *res = new db::DeepRegion (dl_out);
res->set_is_merged (true);
return res;
}
RegionDelegate *

View File

@ -138,11 +138,7 @@ public:
virtual Edges edges (const EdgeFilterBase *) const;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter)
{
return filtered (filter);
}
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter);
virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const;
virtual RegionDelegate *merged_in_place ();
@ -226,6 +222,7 @@ public:
protected:
virtual void merged_semantics_changed ();
void set_is_merged (bool f);
private:
DeepRegion &operator= (const DeepRegion &other);
@ -233,6 +230,7 @@ private:
DeepLayer m_deep_layer;
mutable DeepLayer m_merged_polygons;
mutable bool m_merged_polygons_valid;
bool m_is_merged;
void init ();
void ensure_merged_polygons_valid () const;

View File

@ -183,6 +183,7 @@ protected:
private:
friend class AsIfFlatRegion;
friend class Region;
db::Shapes &raw_polygons () { return m_polygons; }

View File

@ -162,6 +162,9 @@ Region::flat_region ()
region->RegionDelegate::operator= (*mp_delegate);
region->insert_seq (begin ());
}
if (mp_delegate) {
region->set_is_merged (mp_delegate->is_merged ());
}
set_delegate (region);
}

View File

@ -60,6 +60,7 @@ TEST(1)
EXPECT_EQ (regions.back ().size (), db::Region (iter).size ());
EXPECT_EQ (regions.back ().bbox (), db::Region (iter).bbox ());
EXPECT_EQ (regions.back ().is_merged (), false);
}
@ -71,6 +72,26 @@ TEST(1)
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au1.gds");
// some operations
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
db::Region r2 (db::RecursiveShapeIterator (ly, ly.cell (top_cell_index), l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, ly.cell (top_cell_index), l3), dss);
EXPECT_EQ (r2.is_merged (), false);
r2.merge ();
EXPECT_EQ (r2.is_merged (), true);
r2 += r3;
EXPECT_EQ (r2.is_merged (), false);
EXPECT_EQ (r2.merged ().is_merged (), true);
EXPECT_EQ (r2.is_merged (), false);
r2.merge ();
EXPECT_EQ (r2.is_merged (), true);
r2.flatten ();
EXPECT_EQ (r2.is_merged (), true);
r2.insert (db::Box (0, 0, 1000, 2000));
EXPECT_EQ (r2.is_merged (), false);
}
TEST(2)
@ -154,6 +175,8 @@ TEST(3_BoolAndNot)
db::Region r42and3 = r42 & r3;
db::Region r42and42 = r42 & r42;
EXPECT_EQ (r2and3.is_merged (), false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -278,6 +301,8 @@ TEST(5_BoolXOR)
db::Region r42xor3 = r42 ^ r3;
db::Region r42xor42 = r42 ^ r42;
EXPECT_EQ (r2xor3.is_merged (), false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -439,7 +464,13 @@ TEST(9_SizingSimple)
db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss);
db::Region r6_sized = r6.sized (-50);
EXPECT_EQ (r6_sized.is_merged (), true);
db::Region r6_sized_aniso = r6.sized (-20, -100);
EXPECT_EQ (r6_sized_aniso.is_merged (), true);
db::Region r6_sized_plus = r6.sized (50);
EXPECT_EQ (r6_sized_plus.is_merged (), false);
db::Region r6_sized_aniso_plus = r6.sized (20, 100);
EXPECT_EQ (r6_sized_aniso_plus.is_merged (), false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -447,6 +478,8 @@ TEST(9_SizingSimple)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r6);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r6_sized);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r6_sized_aniso);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r6_sized_plus);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r6_sized_aniso_plus);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au9a.gds");
@ -565,6 +598,7 @@ TEST(9_SizingWithBoolean)
r1_sized -= r1;
db::Region r1_sized_aniso = r1.sized (1000, 2000);
r1_sized_aniso -= r1;
EXPECT_EQ (r1_sized_aniso.is_merged (), false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -603,6 +637,8 @@ TEST(10_HullsAndHoles)
db::Region hulls = r1_sized.hulls ();
db::Region holes = r1_sized.holes ();
EXPECT_EQ (hulls.is_merged (), true);
EXPECT_EQ (holes.is_merged (), true);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -673,6 +709,7 @@ TEST(12_GridSnap)
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r3snapped = r3.snapped (50, 50);
EXPECT_EQ (r3snapped.is_merged (), false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -704,6 +741,7 @@ TEST(13_Edges)
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Edges r3edges = r3.edges ();
EXPECT_EQ (r3edges.is_merged (), true);
db::EdgeLengthFilter f (0, 500, true);
db::Edges r3edges_filtered = r3.edges (f);
@ -764,6 +802,8 @@ TEST(14_Interacting)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), r6.selected_overlapping (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), r6.selected_not_overlapping (r1));
EXPECT_EQ (r2.selected_interacting (r1).is_merged (), true);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au14.gds");
}
@ -791,6 +831,9 @@ TEST(15_Filtered)
db::Region af1_filtered = r1.filtered (af1);
db::RegionAreaFilter af1inv (0, 1000000000, true);
db::Region af1_else = r1.filtered (af1inv);
EXPECT_EQ (af1_filtered.is_merged (), true);
EXPECT_EQ (af1_else.is_merged (), true);
{
db::Layout target;

Binary file not shown.