diff --git a/scripts/create_drc_samples.rb b/scripts/create_drc_samples.rb index f7963be5d..2f0da729b 100644 --- a/scripts/create_drc_samples.rb +++ b/scripts/create_drc_samples.rb @@ -452,6 +452,22 @@ run_demo gen, "input1.drc(enclosing(input2) < 2.0.um)", "drc_enc1u.png" run_demo gen, "input1.drc(enclosing(input2,\n"+ " projection) < 2.0.um)", "drc_enc2u.png" +class Gen + def produce(s1, s2) + s1.insert(RBA::Box::new(3000, 0, 6000, 6000)) + s2.insert(RBA::Box::new(0, 1000, 6000, 7000)) + end +end + +gen = Gen::new + +run_demo gen, "input1.enclosed(input2, 2.0.um)", "drc_encd1.png" +run_demo gen, "input1.enclosed(input2, 2.0.um, projection)", "drc_encd2.png" + +run_demo gen, "input1.drc(enclosed(input2) < 2.0.um)", "drc_encd1u.png" +run_demo gen, "input1.drc(enclosed(input2,\n"+ + " projection) < 2.0.um)", "drc_encd2u.png" + class Gen def produce(s1, s2) diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index 9f2759c1a..9fbdf518f 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -460,6 +460,11 @@ static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionO return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); } +static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +{ + return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); +} + static db::CompoundRegionOperationNode *new_perimeter_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits::perimeter_type pmin, db::coord_traits::perimeter_type pmax) { check_non_null (input, "input"); @@ -673,6 +678,11 @@ Class decl_CompoundRegionOperationNode ("db", " gsi::constructor ("new_enclosing_check", &new_enclosing_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), "@brief Creates a node providing an inside (enclosure) check.\n" ) + + gsi::constructor ("new_enclosed_check", &new_enclosed_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + "@brief Creates a node providing an enclosed (secondary enclosing primary) check.\n" + "\n" + "This method has been added in version 0.27.5.\n" + ) + gsi::constructor ("new_perimeter_filter", &new_perimeter_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits::perimeter_type>::max (), "max"), "@brief Creates a node filtering the input by perimeter.\n" "This node renders the input if the perimeter is between pmin and pmax (exclusively). If 'inverse' is set to true, the " diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 84a0c9f6d..e302557cf 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -1160,7 +1160,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". " "If you don't want to specify one threshold, pass nil to the respective value.\n" ) + - method_ext ("inside_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), + method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), "@brief Performs an inside check with options\n" "@param d The minimum distance for which the edges are checked\n" "@param other The other edge collection against which to check\n" @@ -1186,6 +1186,8 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "It is sufficient if the projection of one edge on the other matches the specified condition. " "The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". " "If you don't want to specify one threshold, pass nil to the respective value.\n" + "\n" + "The 'enclosed_check' alias was introduced in version 0.27.5.\n" ) + method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), "@brief Performs an enclosing check with options\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index f7e560d39..621235460 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -2591,7 +2591,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + - method_ext ("inside_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), "@brief Performs an inside check with options\n" "@param d The minimum distance for which the polygons are checked\n" "@param other The other region against which to check\n" @@ -2639,6 +2639,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. " "The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n" + "The 'enclosed_check' alias was introduced in version 0.27.5.\n" ) + method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), "@brief Performs an overlap check with options\n" diff --git a/src/drc/drc/built-in-macros/_drc_complex_ops.rb b/src/drc/drc/built-in-macros/_drc_complex_ops.rb index e0d2ea017..48b534a37 100644 --- a/src/drc/drc/built-in-macros/_drc_complex_ops.rb +++ b/src/drc/drc/built-in-macros/_drc_complex_ops.rb @@ -1888,7 +1888,7 @@ class DRCOpNodeCheck < DRCOpNodeWithCompare factory = { :width => :new_width_check, :space => :new_space_check, :notch => :new_notch_check, :separation => :new_separation_check, :isolated => :new_isolated_check, :overlap => :new_overlap_check, - :enclosing => :new_enclosing_check }[self.check] + :enclosing => :new_enclosing_check, :enclosed => :new_enclosed_check }[self.check] oargs = [] if self.other diff --git a/src/drc/drc/built-in-macros/_drc_cop_integration.rb b/src/drc/drc/built-in-macros/_drc_cop_integration.rb index 58b5518a4..e299350f7 100644 --- a/src/drc/drc/built-in-macros/_drc_cop_integration.rb +++ b/src/drc/drc/built-in-macros/_drc_cop_integration.rb @@ -1042,6 +1042,84 @@ CODE # actual edges from the first input (see \separation for an example). # + # %DRC% + # @name enclosed + # @brief Performs an enclosing check (other enclosing layer) + # @synopsis enclosed(other [, options ]) (in conditions) + # @synopsis enclosed(layer, other [, options ]) + # + # This check verifies if the polygons of the input layer are enclosed by shapes + # of the other input layer by a certain distance. + # It has manifold options. See \Layer#width for the basic options such + # as metrics, projection and angle constraints etc. This check also features + # opposite and rectangle filtering. See \Layer#separation for details about opposite and + # rectangle error filtering. + # + # This function is essentially the reverse of \enclosing. In case of + # "enclosed", the other layer must be bigger than the primary layer. + # + # @h3 Classic mode @/h3 + # + # This function can be used in classic mode with a layer argument. In this case it + # is equivalent to "layer.enclosed" (see \Layer#enclosed). + # + # @code + # # classic "enclosed" check for < 0.2 um + # in = layer(1, 0) + # other = layer(2, 0) + # errors = enclosed(in, other, 0.2.um) + # @/code + # + # @h3 Universal DRC @/h3 + # + # The version without a first layer is intended for use within \DRC# expressions + # together with the "universal DRC" method \Layer#drc. In this case, this function needs to be + # put into a condition to specify the check constraints. The other options + # of \Layer#enclosed (e.g. metrics, projection constraints, angle limits etc.) + # apply to this version too: + # + # @code + # # universal DRC "enclosed" check for < 0.2 um + # in = layer(1, 0) + # other = layer(2, 0) + # errors = in.drc(enclosed(other) < 0.2.um) + # @/code + # + # The conditions may involve an upper and lower limit. The following examples + # illustrate the use of this function with conditions: + # + # @code + # out = in.drc(enclosed(other) < 0.2.um) + # out = in.drc(enclosed(other) <= 0.2.um) + # out = in.drc(enclosed(other) > 0.2.um) + # out = in.drc(enclosed(other) >= 0.2.um) + # out = in.drc(enclosed(other) == 0.2.um) + # out = in.drc(enclosed(other) != 0.2.um) + # out = in.drc(0.1.um <= enclosed(other) < 0.2.um) + # @/code + # + # The result of the enclosed check are edges or edge pairs forming the markers. + # These markers indicate the presence of the specified condition. + # + # With a lower and upper limit, the results are edges marking the positions on the + # primary shape where the condition is met. + # With a lower limit alone, the results are edge pairs which are formed by two identical, but opposite edges attached to + # the primary shape. Without an upper limit only, the first edge of the marker is attached to the + # primary shape while the second edge is attached to the shape of the "other" layer. + # + # @table + # @tr + # @td @img(/images/drc_encd1u.png) @/td + # @td @img(/images/drc_encd2u.png) @/td + # @/tr + # @/table + # + # When "larger than" constraints are used, this function will produce the edges from the + # first layer only. The result will still be edge pairs for consistency, but each edge pair holds one edge from + # the original polygon plus a reverse copy of that edge in the second member. Use "first_edges" to extract the + # actual edges from the first input (see \separation for an example). + # + # %DRC% # @name separation # @brief Performs a separation check @@ -1367,6 +1445,7 @@ CODE %w( enclosing + enclosed isolated notch overlap diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index f5fc0e9cf..3600355ca 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -1751,6 +1751,7 @@ CODE %w( enc enclosing + enclosed overlap sep separation diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 182886121..2cb31656a 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -3756,7 +3756,7 @@ CODE # %DRC% # @name enclosing - # @brief An enclosing check + # @brief An enclosing check (layer enclosing other_layer) # @synopsis layer.enclosing(other_layer, value [, options]) # @synopsis layer.enc(other_layer, value [, options]) # @@ -3764,8 +3764,8 @@ CODE # the \DRC framework. These variants have more options and are more intuitive to use. # See \global#enclosing for more details. # - # This method checks whether layer encloses (is bigger than) other_layer by the - # given dimension. Locations, where this is not the case will be reported in form + # This method checks whether layer encloses (is bigger than) other_layer by not less than the + # given distance value. Locations, where the distance is less will be reported in form # of edge pair error markers. # Locations, where both edges coincide will be reported as errors as well. Formally # such locations form an enclosure with a distance of 0. Locations, where other_layer @@ -3794,13 +3794,48 @@ CODE # @/tr # @/table - %w(width space overlap enclosing separation isolated notch).each do |f| + # %DRC% + # @name enclosed + # @brief An enclosing check (other_layer enclosing layer) + # @synopsis layer.enclosed(other_layer, value [, options]) + # + # @b Note: @/b "enclosed" is available as operators for the "universal DRC" function \drc within + # the \DRC framework. These variants have more options and are more intuitive to use. + # See \global#enclosed for more details. + # + # This method checks whether layer is enclosed by (is inside of) other_layer by not less than the + # given distance value. Locations, where the distance is less will be reported in form + # of edge pair error markers. + # Locations, where both edges coincide will be reported as errors as well. Formally + # such locations form an enclosure with a distance of 0. Locations, where other_layer + # is inside layer will not be reported as errors. Such regions can be detected + # by \inside or a boolean "not" operation. + # + # The options are the same as for \separation. + # + # This method is available for edge and polygon layers. + # + # As for the other DRC methods, merged semantics applies. + # + # Distance values can be given as floating-point values (in micron) or integer values (in + # database units). To explicitly specify the unit, use the unit denominators. + # + # The following images show the effect of two enclosed checks (red: input1, blue: input2): + # + # @table + # @tr + # @td @img(/images/drc_encd1.png) @/td + # @td @img(/images/drc_encd2.png) @/td + # @/tr + # @/table + + %w(width space overlap enclosing enclosed separation isolated notch).each do |f| eval <<"CODE" def #{f}(*args) @engine._context("#{f}") do - if :#{f} == :width || :#{f} == :space || :#{f} == :overlap || :#{f} == :enclosing || :#{f} == :separation + if :#{f} == :width || :#{f} == :space || :#{f} == :overlap || :#{f} == :enclosed || :#{f} == :enclosing || :#{f} == :separation requires_edges_or_region else requires_region diff --git a/src/lay/lay/doc/about/drc_ref_global.xml b/src/lay/lay/doc/about/drc_ref_global.xml index 96c622861..34d3d7f07 100644 --- a/src/lay/lay/doc/about/drc_ref_global.xml +++ b/src/lay/lay/doc/about/drc_ref_global.xml @@ -536,6 +536,85 @@ See Source#edges for a description

"enc" is the short form for enclosing.

+

"enclosed" - Performs an enclosing check (other enclosing layer)

+ +

Usage:

+
    +
  • enclosed(other [, options ]) (in conditions)
  • +
  • enclosed(layer, other [, options ])
  • +
+

+This check verifies if the polygons of the input layer are enclosed by shapes +of the other input layer by a certain distance. +It has manifold options. See Layer#width for the basic options such +as metrics, projection and angle constraints etc. This check also features +opposite and rectangle filtering. See Layer#separation for details about opposite and +rectangle error filtering. +

+This function is essentially the reverse of enclosing. In case of +"enclosed", the other layer must be bigger than the primary layer. +

+

Classic mode

+

+This function can be used in classic mode with a layer argument. In this case it +is equivalent to "layer.enclosed" (see Layer#enclosed). +

+

+# classic "enclosed" check for < 0.2 um
+in = layer(1, 0)
+other = layer(2, 0)
+errors = enclosed(in, other, 0.2.um)
+
+

+

Universal DRC

+

+The version without a first layer is intended for use within DRC expressions +together with the "universal DRC" method Layer#drc. In this case, this function needs to be +put into a condition to specify the check constraints. The other options +of Layer#enclosed (e.g. metrics, projection constraints, angle limits etc.) +apply to this version too: +

+

+# universal DRC "enclosed" check for < 0.2 um
+in = layer(1, 0)
+other = layer(2, 0)
+errors = in.drc(enclosed(other) < 0.2.um)
+
+

+The conditions may involve an upper and lower limit. The following examples +illustrate the use of this function with conditions: +

+

+out = in.drc(enclosed(other) < 0.2.um)
+out = in.drc(enclosed(other) <= 0.2.um)
+out = in.drc(enclosed(other) > 0.2.um)
+out = in.drc(enclosed(other) >= 0.2.um)
+out = in.drc(enclosed(other) == 0.2.um)
+out = in.drc(enclosed(other) != 0.2.um)
+out = in.drc(0.1.um <= enclosed(other) < 0.2.um)
+
+

+The result of the enclosed check are edges or edge pairs forming the markers. +These markers indicate the presence of the specified condition. +

+With a lower and upper limit, the results are edges marking the positions on the +primary shape where the condition is met. +With a lower limit alone, the results are edge pairs which are formed by two identical, but opposite edges attached to +the primary shape. Without an upper limit only, the first edge of the marker is attached to the +primary shape while the second edge is attached to the shape of the "other" layer. +

+ + + + + +
+

+When "larger than" constraints are used, this function will produce the edges from the +first layer only. The result will still be edge pairs for consistency, but each edge pair holds one edge from +the original polygon plus a reverse copy of that edge in the second member. Use "first_edges" to extract the +actual edges from the first input (see separation for an example). +

"enclosing" - Performs an enclosing check

Usage:

diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml index b86cc8e19..56dfbe4c8 100644 --- a/src/lay/lay/doc/about/drc_ref_layer.xml +++ b/src/lay/lay/doc/about/drc_ref_layer.xml @@ -778,7 +778,44 @@ individual ones unless raw mode is chosen.

See enclosing for a description of that method

-

"enclosing" - An enclosing check

+

"enclosed" - An enclosing check (other_layer enclosing layer)

+ +

Usage:

+
    +
  • layer.enclosed(other_layer, value [, options])
  • +
+

+Note: "enclosed" is available as operators for the "universal DRC" function drc within +the DRC framework. These variants have more options and are more intuitive to use. +See enclosed for more details. +

+This method checks whether layer is enclosed by (is inside of) other_layer by not less than the +given distance value. Locations, where the distance is less will be reported in form +of edge pair error markers. +Locations, where both edges coincide will be reported as errors as well. Formally +such locations form an enclosure with a distance of 0. Locations, where other_layer +is inside layer will not be reported as errors. Such regions can be detected +by inside or a boolean "not" operation. +

+The options are the same as for separation. +

+This method is available for edge and polygon layers. +

+As for the other DRC methods, merged semantics applies. +

+Distance values can be given as floating-point values (in micron) or integer values (in +database units). To explicitly specify the unit, use the unit denominators. +

+The following images show the effect of two enclosed checks (red: input1, blue: input2): +

+ + + + + +
+

+

"enclosing" - An enclosing check (layer enclosing other_layer)

Usage:

    @@ -790,8 +827,8 @@ See enclosing for a description of that method the DRC framework. These variants have more options and are more intuitive to use. See enclosing for more details.

    -This method checks whether layer encloses (is bigger than) other_layer by the -given dimension. Locations, where this is not the case will be reported in form +This method checks whether layer encloses (is bigger than) other_layer by not less than the +given distance value. Locations, where the distance is less will be reported in form of edge pair error markers. Locations, where both edges coincide will be reported as errors as well. Formally such locations form an enclosure with a distance of 0. Locations, where other_layer diff --git a/src/lay/lay/doc/images/drc_encd1.png b/src/lay/lay/doc/images/drc_encd1.png new file mode 100644 index 000000000..4be32165a Binary files /dev/null and b/src/lay/lay/doc/images/drc_encd1.png differ diff --git a/src/lay/lay/doc/images/drc_encd1u.png b/src/lay/lay/doc/images/drc_encd1u.png new file mode 100644 index 000000000..8c9403be8 Binary files /dev/null and b/src/lay/lay/doc/images/drc_encd1u.png differ diff --git a/src/lay/lay/doc/images/drc_encd2.png b/src/lay/lay/doc/images/drc_encd2.png new file mode 100644 index 000000000..88e7ad63e Binary files /dev/null and b/src/lay/lay/doc/images/drc_encd2.png differ diff --git a/src/lay/lay/doc/images/drc_encd2u.png b/src/lay/lay/doc/images/drc_encd2u.png new file mode 100644 index 000000000..ec3615fca Binary files /dev/null and b/src/lay/lay/doc/images/drc_encd2u.png differ diff --git a/src/lay/lay/layDRCLVSHelpResources.qrc b/src/lay/lay/layDRCLVSHelpResources.qrc index d11b89b5e..2ad75afed 100644 --- a/src/lay/lay/layDRCLVSHelpResources.qrc +++ b/src/lay/lay/layDRCLVSHelpResources.qrc @@ -36,6 +36,10 @@ doc/images/drc_enc2.png doc/images/drc_enc1u.png doc/images/drc_enc2u.png + doc/images/drc_encd1.png + doc/images/drc_encd2.png + doc/images/drc_encd1u.png + doc/images/drc_encd2u.png doc/images/drc_overlap1.png doc/images/drc_overlap2.png doc/images/drc_overlap1u.png