From ddcfda8761b50ae25b6303db8fb8bc55466cae6e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 13 Feb 2019 17:17:03 +0100 Subject: [PATCH] Some optimization: keep merged state in deep region. --- src/db/db/dbDeepEdges.cc | 69 ++++++++++------- src/db/db/dbDeepEdges.h | 4 + src/db/db/dbDeepRegion.cc | 98 ++++++++++++++++++------- src/db/db/dbDeepRegion.h | 8 +- src/db/db/dbFlatRegion.h | 1 + src/db/db/dbRegion.cc | 3 + src/db/unit_tests/dbDeepRegionTests.cc | 43 +++++++++++ testdata/algo/deep_region_au9a.gds | Bin 1866 -> 2698 bytes 8 files changed, 168 insertions(+), 58 deletions(-) diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index e7d1eea13..9f64db300 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -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 (m_deep_layer.layout ()); + } else { - db::hier_clusters 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 (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 &cc = hc.clusters_per_cell (c->cell_index ()); - for (db::connected_clusters::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 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 &cc = hc.clusters_per_cell (c->cell_index ()); + for (db::connected_clusters::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; } diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index d7c4f3e01..1b4c448ab 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -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; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 133e45c2a..9955d9486 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -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 (m_deep_layer.layout ()); + } else { - db::hier_clusters 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 (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 &cc = hc.clusters_per_cell (c->cell_index ()); - for (db::connected_clusters::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 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 &cc = hc.clusters_per_cell (c->cell_index ()); + for (db::connected_clusters::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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&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 * diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 8eec5ab51..153820931 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -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; diff --git a/src/db/db/dbFlatRegion.h b/src/db/db/dbFlatRegion.h index d4824fef4..8f84c8d66 100644 --- a/src/db/db/dbFlatRegion.h +++ b/src/db/db/dbFlatRegion.h @@ -183,6 +183,7 @@ protected: private: friend class AsIfFlatRegion; + friend class Region; db::Shapes &raw_polygons () { return m_polygons; } diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index 18562208d..fb976cd9d 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -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); } diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 648c39d24..2126434eb 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -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; diff --git a/testdata/algo/deep_region_au9a.gds b/testdata/algo/deep_region_au9a.gds index 6182a96617420d6d814885d0aa79b04b342e6ef5..16dd35174b2f8a95a8b0c1100f3693faf6fd287f 100644 GIT binary patch literal 2698 zcmai$Pe>GT6vyAr&d%&^tEhMokr3-pA|xebLZKq1B^H~6goJeH5FR{4L_{nRLLNk- zgHVKYunrNP!b1lSA)UfQ2M-Za5S?UC(XM}{@0&M|-;B(-UOvnF`hCCO`|jJFC5J3) zg4$A+`-?29qegP*Sok$%EoXFOkf=GGxiIkT?3MMm<#R);rqK^z$f>g^Pfoo>L|qMO&)fUtdHYY9M5#xf=N(sSok@0MtRG#z`#Q)zB5O#gb>nyG z(3@r*XJqWgX|nS~`6j(}fp57#gOhLrzD2y6FUP1(YpO(q4!F}oLWcwYqkRr!HOW2F z?dZ`gTm;G0Lg$-a`L*CPM7P`L_-2yXe=1z5&yBL>H=$8QXuF^R!+= z|Hwp+mvPr0hR&?im4!a&Z}@znJBPD>BF}(yQR+hN>oc6M&ez5Bd5>9V%DMDJsr6cZ zydTTr=XaA2YVUe|SKc;Lo4ppq9VptFc=1QnGfmoUEPfPu9*X zBx~ollC|OPWUW|A)+RTMmW}y!Q<>x^vga{f{L-m@Hq<(v+~Ey~JRvIc@Xx{zx^wV9 zH`F?wP+@=M8?Z71|0?{Ti*2s17-}8gz+r#n6JF_rzXN{I-G=|Kq1N#Y6ZS_oxH61S XK^cB9i%qU>8fqP%B;St>v~Btii3Fs@ delta 133 zcmeAYJ;kTQz{bGD6u}_F$i)7bfr){WL5RVEK@^!iQAt%8n{d>0Y{Hva80}c(*cljP TSaF)TS%KpTBO6c+3kw4PdNL4t