diff --git a/src/db/db/dbRegionDelegate.cc b/src/db/db/dbRegionDelegate.cc index 3f8997967..2ce4e640d 100644 --- a/src/db/db/dbRegionDelegate.cc +++ b/src/db/db/dbRegionDelegate.cc @@ -33,7 +33,7 @@ RegionDelegate::RegionDelegate () m_base_verbosity = 30; m_report_progress = false; m_merged_semantics = true; - m_join_properties_on_merge = true; + m_join_properties_on_merge = false; m_strict_handling = false; m_merge_min_coherence = false; } diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index b2fcb38d4..1bd93d5d0 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -1059,9 +1059,9 @@ static void break_polygons (db::Region *r, size_t max_vertex_count, double max_a r->process (db::PolygonBreaker (max_vertex_count, max_area_ratio)); } -static db::Region &merge_ext1 (db::Region *r, int min_wc, bool jpm) +static db::Region &merge_ext1 (db::Region *r, int min_wc) { - r->merge (false, std::max (0, min_wc - 1), jpm); + r->merge (false, std::max (0, min_wc - 1)); return *r; } @@ -1071,9 +1071,9 @@ static db::Region &merge_ext2 (db::Region *r, bool min_coherence, int min_wc, bo return *r; } -static db::Region merged_ext1 (db::Region *r, int min_wc, bool jpm) +static db::Region merged_ext1 (db::Region *r, int min_wc) { - return r->merged (false, std::max (0, min_wc - 1), jpm); + return r->merged (false, std::max (0, min_wc - 1)); } static db::Region merged_ext2 (db::Region *r, bool min_coherence, int min_wc, bool jpm) @@ -1747,14 +1747,13 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", method ("join_properties_on_merge=", &db::Region::set_join_properties_on_merge, gsi::arg ("f"), "@brief Sets a flag indication whether to join properties on merge\n" "\n" - "When this flag is set to true (the default), properties are joined on 'merge'.\n" + "When this flag is set to true, properties are joined on 'merge'.\n" "That is: shapes merging into bigger shapes will have their properties joined.\n" - "With the flag set to false, 'merge' will not join properties and return merged\n" + "With the flag set to false (the default), 'merge' will not join properties and return merged\n" "shapes only if the sub-shapes have the same properties - i.e. properties form\n" "different classes on merge.\n" "\n" - "This attribute has been introduced in version 0.30.3. The default has changed from 'don't join properties' to " - "'join properties' in that version." + "This attribute has been introduced in version 0.30.3." ) + method ("join_properties_on_merge?", &db::Region::join_properties_on_merge, "@brief Gets a flag indication whether to join properties on merge\n" @@ -2398,13 +2397,13 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@return The region after it has been merged (self).\n" "\n" "Merging removes overlaps and joins touching polygons.\n" - "If the region is already merged, this method does nothing\n" + "If the region is already merged, this method does nothing.\n" + "This method will behave according to the settings of the \\min_coherence and \\join_properties_on_merge attributes." ) + - method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true), + method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"), "@brief Merge the region with options\n" "\n" "@param min_wc Overlap selection\n" - "@param join_properties_on_merge See below\n" "@return The region after it has been merged (self).\n" "\n" "Merging removes overlaps and joins touching polygons.\n" @@ -2412,16 +2411,9 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "polygons overlap. The value specifies the number of polygons that need to overlap. A value of 2 " "means that output is only produced if two or more polygons overlap.\n" "\n" - "The 'join_properties_on_merge' argument indicates how properties should be handled: if true, " - "the properties of the constituents are joined and attached to the merged shape. If false, " - "only shapes with the same properties are merged - i.e. different properties form shape classes " - "that are merged individually.\n" - "\n" - "This method is equivalent to \"merge(false, min_wc, join_properties_on_merge).\n" - "\n" - "'join_properties_on_merge' has been added in version 0.30.3." + "This method is equivalent to \"merge(false, min_wc, false).\n" ) + - method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true), + method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", false), "@brief Merge the region with options\n" "\n" "@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n" @@ -2449,24 +2441,24 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merging removes overlaps and joins touching polygons.\n" "If the region is already merged, this method does nothing.\n" + "This method will behave according to the settings of the \\min_coherence and \\join_properties_on_merge attributes.\n" "In contrast to \\merge, this method does not modify the region but returns a merged copy.\n" ) + - method_ext ("merged", &merged_ext1, gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true), + method_ext ("merged", &merged_ext1, gsi::arg ("min_wc"), "@brief Returns the merged region (with options)\n" "\n" "@param min_wc Overlap selection\n" - "@param join_properties_on_merge See below\n" "@return The region after it has been merged.\n" "\n" "This version provides one additional options: \"min_wc\" controls whether output is only produced if multiple " "polygons overlap. The value specifies the number of polygons that need to overlap. A value of 2 " "means that output is only produced if two or more polygons overlap.\n" "\n" - "This method is equivalent to \"merged(false, min_wc, join_properties_on_merge)\".\n" + "This method is equivalent to \"merged(false, min_wc, false)\".\n" "\n" "In contrast to \\merge, this method does not modify the region but returns a merged copy.\n" ) + - method_ext ("merged", &merged_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true), + method_ext ("merged", &merged_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", false), "@brief Returns the merged region (with options)\n" "\n" "@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n" diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index fd714701f..a5ecd88b7 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2151,6 +2151,8 @@ TEST(40_BoolWithProperties) db::RecursiveShapeIterator si1 (ly, top_cell, l1); si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ()); db::Region r1 (si1, dss); + EXPECT_EQ (r1.join_properties_on_merge (), false); + r1.set_join_properties_on_merge (true); EXPECT_EQ (r1.join_properties_on_merge (), true); r1.set_join_properties_on_merge (false); EXPECT_EQ (r1.join_properties_on_merge (), false); diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index bda81aac9..ee8a7ad42 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -5103,18 +5103,66 @@ CODE # Like \merged, but modifies the input and returns a reference to the # new layer. - def merged(*args) + def merged(overlap_count = 1) @engine._context("merged") do requires_edges_or_region - aa = args.collect { |a| @engine._prep_value(a) } + aa = [ @engine._prep_value(overlap_count) ] DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :merged, *aa)) end end - def merge(*args) + def merge(overlap_count = 1) @engine._context("merge") do requires_edges_or_region - aa = args.collect { |a| @engine._prep_value(a) } + aa = [ @engine._prep_value(overlap_count) ] + if @engine.is_tiled? + # in tiled mode, no modifying versions are available + self.data = @engine._tcmd(self.data, 0, self.data.class, :merged, *aa) + else + @engine._tcmd(self.data, 0, self.data.class, :merge, *aa) + end + self + end + end + + # %DRC% + # @name merged_props + # @brief Merges and joins properties of the shapes + # @synopsis layer.merged_props([overlap_count]) + # + # Returns the merged input. Unlike the plain \merged method, this version + # will join properties on merged shapes. Properties with the same name + # will be merged by computing the maximum value of the parts. + # + # For example: + # Properties @tt { "A" => 17, "C" => 2.5 } @/tt merged with @tt { "A" => 1, "B" => "a text" } @/tt will give + # @tt { "A" => 17, "B" => "a text", "C" => 2.5 } @/tt. + # + # The plain \merged method will treat shapes with different properties as + # separate entities and will not merge them. + # + # Currently, this method is available for polygon layers only. + + # %DRC% + # @name merge_props + # @brief Merges the layer and joins the properties (modifies the layer) + # @synopsis layer.merge_props([overlap_count]) + # + # Like \merged_props, but modifies the input and returns a reference to the + # new layer. + + def merged_props(overlap_count = 1) + @engine._context("merged") do + requires_region + aa = [ self.data.min_coherence, @engine._prep_value(overlap_count), true ] + DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :merged, *aa)) + end + end + + def merge_props(overlap_count = 1) + @engine._context("merge") do + requires_region + aa = [ self.data.min_coherence, @engine._prep_value(overlap_count), true ] if @engine.is_tiled? # in tiled mode, no modifying versions are available self.data = @engine._tcmd(self.data, 0, self.data.class, :merged, *aa) diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index c0850edb1..e5c740e76 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -2003,3 +2003,13 @@ TEST(140d_target_modification) { run_test (_this, "140", true); } + +TEST(141_merge_properties) +{ + run_test (_this, "141", false); +} + +TEST(141d_merge_properties) +{ + run_test (_this, "141", true); +} diff --git a/testdata/drc/drcSimpleTests_141.drc b/testdata/drc/drcSimpleTests_141.drc new file mode 100644 index 000000000..89ed7d0f0 --- /dev/null +++ b/testdata/drc/drcSimpleTests_141.drc @@ -0,0 +1,24 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0, enable_props) + +l1.output(1, 0) + +l1.merged_props.output(10, 0) + +l1d = l1.dup +l1d.merge_props +l1d.output(11, 0) + +l1.merged_props(2).output(20, 0) + +l1d = l1.dup +l1d.merge_props(2) +l1d.output(21, 0) + diff --git a/testdata/drc/drcSimpleTests_141.gds b/testdata/drc/drcSimpleTests_141.gds new file mode 100644 index 000000000..d17af6401 Binary files /dev/null and b/testdata/drc/drcSimpleTests_141.gds differ diff --git a/testdata/drc/drcSimpleTests_au141.gds b/testdata/drc/drcSimpleTests_au141.gds new file mode 100644 index 000000000..20af5373e Binary files /dev/null and b/testdata/drc/drcSimpleTests_au141.gds differ diff --git a/testdata/drc/drcSimpleTests_au141d.gds b/testdata/drc/drcSimpleTests_au141d.gds new file mode 100644 index 000000000..76f8373db Binary files /dev/null and b/testdata/drc/drcSimpleTests_au141d.gds differ diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index 761fa65a7..c7ec7d28e 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -1637,12 +1637,12 @@ class DBRegion_TestClass < TestBase s = r.each.collect(&:to_s).join(";") assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}") rr = r.dup - rr.join_properties_on_merge = false - assert_equal(rr.join_properties_on_merge, false) + rr.join_properties_on_merge = true + assert_equal(rr.join_properties_on_merge, true) s = rr.each_merged.collect(&:to_s).join(";") - assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}") - s = r.each_merged.collect(&:to_s).join(";") assert_equal(s, "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0) props={1=>one}") + s = r.each_merged.collect(&:to_s).join(";") + assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}") r = RBA::Region::new r.insert(RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one" }))