Doc update, fixed DRC's 'switch' function

This commit is contained in:
Matthias Koefferlein 2021-01-15 00:31:26 +01:00
parent 80996a77fb
commit 8051bef9ac
9 changed files with 499 additions and 284 deletions

View File

@ -47,8 +47,8 @@ def escape(mod, s)
s.gsub("&", "&").
gsub("<", "&lt;").
gsub(">", "&gt;").
gsub(/\\([\w:#]+)/) { create_ref(mod, $1) }.
gsub(/\\\\([\w:#]+)/) { create_link(mod, $1) }.
gsub(/\\([\w:#]+)/) { create_ref(mod, $1) }.
gsub(/RBA::([\w#]+)/) { create_class_doc_ref($1) }
end

View File

@ -27,51 +27,51 @@ module DRC
# The following global functions are relevant for the DRC expressions:
#
# @ul
# @li \\global#angle @/li
# @li \\global#area @/li
# @li \\global#area_ratio @/li
# @li \\global#bbox_area_ratio @/li
# @li \\global#bbox_height @/li
# @li \\global#bbox_max @/li
# @li \\global#bbox_min @/li
# @li \\global#bbox_width @/li
# @li \\global#case @/li
# @li \\global#corners @/li
# @li \\global#covering @/li
# @li \\global#enc @/li
# @li \\global#enclosing @/li
# @li \\global#extent_refs @/li
# @li \\global#extents @/li
# @li \\global#foreign @/li
# @li \\global#holes @/li
# @li \\global#hulls @/li
# @li \\global#if_all @/li
# @li \\global#if_any @/li
# @li \\global#if_none @/li
# @li \\global#inside @/li
# @li \\global#interacting @/li
# @li \\global#iso @/li
# @li \\global#length @/li
# @li \\global#middle @/li
# @li \\global#notch @/li
# @li \\global#odd_polygons @/li
# @li \\global#outside @/li
# @li \\global#overlap @/li
# @li \\global#overlapping @/li
# @li \\global#perimeter @/li
# @li \\global#primary @/li
# @li \\global#rectangles @/li
# @li \\global#rectilinear @/li
# @li \\global#relative_height @/li
# @li \\global#rounded_corners @/li
# @li \\global#secondary @/li
# @li \\global#separation @/li
# @li \\global#sep @/li
# @li \\global#sized @/li
# @li \\global#smoothed @/li
# @li \\global#space @/li
# @li \\global#squares @/li
# @li \\global#width @/li
# @li \global#angle @/li
# @li \global#area @/li
# @li \global#area_ratio @/li
# @li \global#bbox_area_ratio @/li
# @li \global#bbox_height @/li
# @li \global#bbox_max @/li
# @li \global#bbox_min @/li
# @li \global#bbox_width @/li
# @li \global#case @/li
# @li \global#corners @/li
# @li \global#covering @/li
# @li \global#enc @/li
# @li \global#enclosing @/li
# @li \global#extent_refs @/li
# @li \global#extents @/li
# @li \global#foreign @/li
# @li \global#holes @/li
# @li \global#hulls @/li
# @li \global#if_all @/li
# @li \global#if_any @/li
# @li \global#if_none @/li
# @li \global#inside @/li
# @li \global#interacting @/li
# @li \global#iso @/li
# @li \global#length @/li
# @li \global#middle @/li
# @li \global#notch @/li
# @li \global#odd_polygons @/li
# @li \global#outside @/li
# @li \global#overlap @/li
# @li \global#overlapping @/li
# @li \global#perimeter @/li
# @li \global#primary @/li
# @li \global#rectangles @/li
# @li \global#rectilinear @/li
# @li \global#relative_height @/li
# @li \global#rounded_corners @/li
# @li \global#secondary @/li
# @li \global#separation @/li
# @li \global#sep @/li
# @li \global#sized @/li
# @li \global#smoothed @/li
# @li \global#space @/li
# @li \global#squares @/li
# @li \global#width @/li
# @/ul
#
# The following documentation will list the methods available for DRC expression objects.
@ -1428,7 +1428,20 @@ class DRCOpNodeCase < DRCOpNode
end
def do_create_node(cache)
RBA::CompoundRegionOperationNode::new_case(self.children.collect { |c| c.create_node(cache) })
nodes = self.children.collect { |c| c.create_node(cache) }
types = []
nodes.each_with_index do |a,index|
if index % 2 == 1
types << a.result_type
end
end
if types.sort.uniq.size > 1
raise("All result arguments need to have the same type (we got '" + types.collect(:to_s).join(",") + "')")
end
RBA::CompoundRegionOperationNode::new_case(nodes)
end
end

View File

@ -18,35 +18,37 @@ module DRC
#
# The key concept for this method are DRC expressions. DRC expressions
# are formed by using predefined keywords like "width", operators like "&"
# and method to build an abstract definition of the operations to perform
# and methods to build an abstract definition of the operations to perform
# within the DRC.
#
# When the DRC function is executed, it will basically visit all shapes
# from the input layer (the one, the "drc" method is called on), collect
# the neighbor shapes from all involved other inputs and run the requested
# operations on each cluster. Currently, "drc" is only available for polygon
# layers.
# from the input layer. This is the layer, the "drc" method is called on.
# While it does, it collects the neighbor shapes from all involved other inputs
# and runs the requested operations on each cluster.
# Currently, "drc" is only available for polygon layers.
#
# The nature of the "drc" operation is that of the loop over all (merged) input
# This way, the nature of the "drc" operation is that of the loop over all (merged) input
# polygons. Within the operation executed on each shape, it's possible to make
# decisions such as "if the shape has an area larger than something, apply this
# operation" etc. This can be achieved with conventional DRC functions too,
# operation" or similar. This often can be achieved with conventional DRC functions too,
# but involves potentially complex and heavy operations such as booleans, interact
# etc. For this reason, the "drc" function may provide a performance benefit.
# etc. For this reason, the "drc" function may provide a better performance.
#
# In addition, within the loop, a single shape from the input layer is presented to
# In addition, within the loop a single shape from the input layer is presented to
# execution engine which runs the operations.
# This allows using operations such as "size" without having to consider
# neigbor polygons growing into the area of the initial shape. In this sense,
# the "drc" function allows seeing the layer as individual polygons rather than
# the "drc" function sees the layer as individual polygons rather than
# a global "sea of polygons". This enables new applications which are otherwise
# difficult to implement.
#
# An important concept in the context of "drc" expressions is the "primary".
# This expression represents a single primary shape. "Secondaries" are shapes
# from other inputs. Primary shapes guide the operation - secondaries without
# @h3 Primaries and secondaries @/h3
#
# An important concept in "drc" expressions is the "primary".
# The primary represents a single shape from the input layer. "Secondaries" are shapes
# from other inputs. Primaries guide the operation - secondaries without
# primaries are not seen. The "drc" operation will look for secondaries within
# a certain distance which is determined from the operations within the
# a certain distance which is determined from the operations from the
# expression to execute. The secondaries collected in this step will not be
# merged, so the secondary polygons may be partial. This is important when
# using measurement operations like "area" on secondary polygons.
@ -70,8 +72,8 @@ module DRC
# out = in.drc(0.2.um < width < 0.5.um)
# @/code
#
# To specify the second input for a two-layer check, specify the second input
# with the check function. Here a two-layer separation check is used (\global#separation):
# To specify the second input for a two-layer check, specify it in brackets in
# the check function. This example shows how to use a two-layer separation check (\global#separation):
#
# @code
# l1 = input(1, 0)
@ -81,10 +83,11 @@ module DRC
#
# The second input of this check function can be a computed expression. In this
# case the local loop will first evaluate the expression for the second input and
# then use it inside the check.
# then use the result for second input in the check. Note that this computation is
# performed locally and separately for each primary and its context.
#
# Options for the checks are also specified inside the brackets. For example,
# to specify a projection metrics for width use:
# to specify projection metrics ("projection") for width use:
#
# @code
# out = in.drc(width(projection) < 0.5.um)
@ -99,26 +102,31 @@ module DRC
# in the DRC expressions, methods are available to filter, process and convert
# these types.
#
# For example, the check produces edge pairs which can be converted into polygons
# For example, all checks produce edge pairs which can be converted into polygons
# using the "polygons" method:
#
# @code
# out = in.drc((width(projection) < 0.5.um).polygons)
# @/code
#
# Note the subtle difference: when putting the "polygons" method inside the "drc"
# brackets, it is executed locally on every checked primary polygon. The result
# may be identical to the global conversion:
# Note a subtle detail: when putting the "polygons" method inside the "drc"
# brackets, it is executed locally on every visited primary polygon. The result
# in this case is identical to the global conversion:
#
# @code
# # same, but with "global" conversion:
# out = in.drc(width(projection) < 0.5.um).polygons
# @/code
#
# but having the check polygons inside the loop opens new opportunities and
# is more efficient in general.
# But having the check polygons inside the loop opens new opportunities and
# is more efficient in general. In the previous example, the local conversion
# will keep a few edge pairs after having converted them to polygons. In
# the global case, all edge pairs are collected first and then converted.
# If there are many edge pairs, this requires more memory and a larger computing
# overhead for managing the bigger number of shapes.
#
# Conversion methods are:
# For the conversion of edges, edge pairs and polygons into other types, these
# methods are provided:
#
# @ul
# @li \DRC#polygons: converts edge pairs to polygons @/li
@ -128,7 +136,7 @@ module DRC
# @li \DRC#corners: can extract corners from polygons @/li
# @/ul
#
# This example decomposes the primary polygons into edges:
# The following example decomposes the primary polygons into edges:
#
# @code
# out = in.drc(primary.edges)
@ -137,19 +145,25 @@ module DRC
# (for backward compatibility you cannot abbreviate "primary.edges" simply as "edges" like
# other functions).
#
# The previous isn't quite exciting as it is equivalent to
# The previous example isn't quite exciting as it is equivalent to
#
# @code
# # Same as above
# out = in.edges
# @/code
#
# But it gets more interesting as within the loop, "edges" delivers the edge set for
# each individual polygon. So this will give you the edges of polygons with more than four corners:
# But it gets more interesting, as within the loop, "edges" delivers the edge set for
# each individual polygon. It's possible to work with this distinct set, so for example
# this will give you the edges of polygons with more than four corners:
#
# @code
# out = in.drc(primary.edges.count > 4)
# @/code
#
# Explanation: "count" is a "quantifier" which takes any kind of set (edges, edge pairs, polygons)
# and returns the set if the number of inhabitants meets the given condition. Otherwise the set
# is skipped. So it will look at the edges and if there are more than four (per primary shape),
# it will forward this set.
#
# The same result can be achieved with classic DRC with "interact" and a figure count, but
# at a much higher computation cost.
@ -166,11 +180,14 @@ module DRC
#
# @h3 Filters @/h3
#
# Filter operators select input polygons or edges based on their properties. These filters are:
# Filter operators select input polygons or edges based on their properties. These filters are provided:
#
# @ul
# @li "\DRC#area": selects polygons based on their area @/li
# @li "\DRC#perimeter": selects polygons based on their perimeter @/li
# @li "\DRC#area_ratio": selects polygons based on their bounding box to polygon area ratio @/li
# @li "\DRC#bbox_aspect_ratio": selects polygons based on their bounding box aspect ratio @/li
# @li "\DRC#relative_height": selects polygons based on their relative height @/li
# @li "\DRC#bbox_min", "\global#bbox_max", "\global#bbox_width", "\global#bbox_height": selects polygons based on their bounding box properties @/li
# @li "\DRC#length": selects edges based on their length @/li
# @li "\DRC#angle": selects edges based on their orientation @/li
@ -196,19 +213,20 @@ module DRC
# "bbox_min" etc. will evaluate a particular dimensions of the polygon's bounding box and
# use the respective dimension for filtering the polygon.
#
# Note that it's basically possible to use the polygon filters on any kind of input.
# Note that it's basically possible to use the polygon filters on any input - computed and secondaries.
# In fact, plain "area" for example is a shortcut for "\global#primary.area" indicating that
# the area of primary shapes are supposed to be computed.
# However, any input other than the primary is not necessarily complete or it may
# consist of multiple polygons. Hence the computed values may be too big or too small.
# It's recommended therefore to use the measurement functions on primary polygons
# only.
# unless you know what you're doing.
#
# @h3 Filter predicates @/h3
#
# The "drc" feature also supports some predicates. "predicates" are boolean values
# indicating a certain condition. A predicate filter works in a way that it only
# passes the polygons
# passes the polygons if the condition is met.
#
# The predicates available currently are:
#
# @ul
@ -219,7 +237,7 @@ module DRC
#
# For the same reason as explained above, it's recommended to use these predicates
# standalone, so they act on primary shapes. It's possible to use the predicates
# on computed shapes or secondary input, but that may not render the desired results.
# on computed shapes or secondaries, but that may not render the desired results.
#
# @h3 Logical NOT operator @/h3
#
@ -234,37 +252,54 @@ module DRC
#
# @h3 Logical combination operators @/h3
#
# The logical "if_any" or "if_all" statements allow connecting multiple
# The logical "if_any" or "if_all" functions allow connecting multiple
# conditions and evaluate to "true" (means: a non-empty shape set) if either
# on input is a non-empty shape set ("if_any") or if all inputs are non-empty
# ("if_all"). For example, this will select all polygons which are rectangles
# one input is a non-empty shape set ("if_any") or if all inputs are non-empty
# ("if_all").
#
# For example, this will select all polygons which are rectangles
# and whose area is larger than 20 quare micrometers:
#
# @code
# out = in.drc(if_all(rectangles, area > 20.0))
# @/code
#
# In fact, "if_all" renders the result of the last expression, provided all
# previous ones are non-empty. So this operation will render rectangles
# sized by 100 nm and skip all other types of polygons:
# "if_all" delivers the primary shape if all of the input expressions
# render a non-empty result.
#
# In contrast to this, the "if_any" operation will deliver the primary shape
# if one of the input expressions renders a non-empty result.
#
# The "\global#switch" function allows selecting one input based on the results of an
# expression. In the two-input form it's equivalent to "if". The first expression
# is the condition. If it evaluates to a non-empty shape set, the result of the
# second expression is taken. Otherwise, the result is empty.
#
# Hence the following code delivers all rectangles sized by 100 nm. All
# other shapes are skipped:
#
# @code
# out = in.drc(if_all(rectangles, sized(100.nm)))
# out = in.drc(switch(rectangles, primary.sized(100.nm)))
# @/code
#
# Contrary to this, the "if_any" operation will render the first non-empty
# expression result and skip the following ones. So this example will
# size all rectangles by 100 nm and leave all other types of polygons
# untouched:
# A third expression will be considered the "else" branch: the result of
# this expression will be taken if the first one is not taken. So this
# example will size all rectangles and leave other shapes untouched:
#
# @code
# out = in.drc(if_any(rectangles.sized(100.nm), primary))
# out = in.drc(switch(rectangles, primary.sized(100.nm), primary))
# @/code
#
# If more expressions are given, they are considered as a sequence of condition/result
# chain (c1, e1, c2, e2, ...) in the sense of "if(c1) return(e1) else if(c2) return(e2) ...".
# So the e1 is taken if c1 is met, e2 is taken when c1 is not met, but c2 is and so forth.
# If there is an odd number of expressions, the last one will be the default expression
# which is taken if none of the conditions is met.
#
# @h3 Polygon manipulations @/h3
#
# The "drc" operations feature polygon manipulations where the input is
# either the primary polygon or derived shapes.
# either the primary, secondaries or derived shapes.
# Manipulations include sizing ("\global#sized"), corner rounding ("\global#rounded_corners"), smoothing ("\global#smoothed")
# and boolean operations.
#
@ -289,7 +324,7 @@ module DRC
# out = l1.drc((primary & secondary(l2)).area > 1.0)
# @/code
#
# The "\global#secondar" operator indicates that "l2" is to be used as secondary input to the "drc" function. Only
# The "\global#secondary" operator indicates that "l2" is to be used as secondary input to the "drc" function. Only
# in this form, the operators of the boolean AND can be reversed:
#
# @code
@ -298,25 +333,26 @@ module DRC
#
# @h3 Quantifiers @/h3
#
# Some filters operate on properties of the full, local shape set.
# Some filters operate on properties of the full, local, per-primary shape set.
# While the loop is executed, the DRC expressions will collect shapes, either
# from the primary, it's neighborhood (secondary) or by deriving shape sets.
# from the primary, it's neighborhood (secondaries) or from deriving shape sets.
#
# Obviously the primary is a simple one: it consists of a single shape, because
# this is how the loop operates. Derived shape sets however can be more complex.
# "Quantifiers" allow to assess properties of the complete, per-primary shape
# set. A simple one is "count" which checks if the number of shapes within
# "Quantifiers" allow assessing properties of the complete, per-primary shape
# set. A simple one is "\DRC#count" which checks if the number of shapes within
# a shape set is within a given range.
#
# Obviously, "primary.count == 1" is always true. The following condition will
# select all primary shapes which have more than 13 corners:
# Obviously, "primary.count == 1" is always true. So using "count" primaries isn't
# much fun. So it's better to use it on derived sets.
# The following condition will select all primary shapes which have more than 13 corners:
#
# @code
# out = in.drc(if_any(primary.corners.count > 13))
# @/code
#
# Note an important detail here: the "if_any" function will render primary
# @b polygons @/b, if the expression inside gives a non-empty result. Without
# Note an important detail here: the "if_any" function will make this statement render primary
# polygons, if the expression inside gives a non-empty result. Without
# "if_any", the result would be the output of "count" which is the set of all
# corners where the corner count is larger than 13.
#
@ -339,12 +375,15 @@ module DRC
# @/code
#
# Note that the first line prepares the operation, but does not execute the area computation
# or the boolean operation. But when the "drc" function executes the operation it will
# only compute the area once as it is represented by the same Ruby object.
# or the boolean operation. But when the "drc" function executes the loop over the primaries it will
# only compute the area once per primary as it is represented by the same Ruby object.
#
# @h3 Summary @/h3
# @h3 Outlook @/h3
#
# DRC expressions are quite rich and powerful. They provide a more intuitive way of
# writing DRC expressions, are more efficient and open new opportunities. DRC
# development is likely to focus on this scheme in the future.
#
# The bottom line is: DRC expressions are quite rich and there is a lot more to be said and written.
# More formal details about the bits and pieces can be found in the \DRC# class documentation.
def drc(op)
@ -375,20 +414,20 @@ module DRC
class DRCEngine
# %DRC%
# @name case
# @name switch
# @brief A conditional selector for the "drc" universal DRC function
# @synopsis case(...)
# @synopsis switch(...)
#
# This function provides a conditional selector for the "drc" function.
# It is used this way:
#
# @code
# out = in.drc(case(c1, r1, c2, r2, ..., cn, rn)
# out = in.drc(case(c1, r1, c2, r2, ..., cn, rn, rdef)
# out = in.drc(switch(c1, r1, c2, r2, ..., cn, rn)
# out = in.drc(switch(c1, r1, c2, r2, ..., cn, rn, rdef)
# @/code
#
# This function will evaluate c1 which is a universal DRC expression (see \Layer#drc).
# If the result is not empty, "case" will evaluate and return r1. Otherwise it
# If the result is not empty, "switch" will evaluate and return r1. Otherwise it
# will continue with c2 and the result of this expression is not empty it will
# return r2. Otherwise it will continue with c3/r3 etc.
#
@ -398,27 +437,16 @@ module DRC
# As a requirement, the result types of all r1..rn expressions and the rdef
# needs to be the same - i.e. all need to render polygons or edges or edge pairs.
def case(*args)
def switch(*args)
self._context("case") do
anum = 1
self._context("switch") do
args = args.collect { |a| self._make_node(a) }
types = []
args.each do |a|
args.each_with_index do |a,index|
if !a.is_a?(DRCOpNode)
raise("All inputs need to be valid compound operation expressions (argument ##{anum} isn't)")
raise("All inputs need to be valid compound operation expressions (argument ##{index + 1} isn't)")
end
if a % 2 == 0
types << a.result_type
end
anum += 1
end
if types.sort.uniq.size > 1
raise("All result arguments need to have the same type (we got '" + types.collect(:to_s).join(",") + "')")
end
DRCOpNodeCase::new(self, args)

View File

@ -3001,7 +3001,7 @@ CODE
# @li @b projecting (in condition) @/b: This specification is equivalent to "projection_limits"
# but is more intuitive, as "projecting" is written with a condition, like
# "projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=".
# Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0".
# Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". @/li
# @li @b transparent @/b: performs the check without shielding (polygon layers only) @/li
# @li @b shielded @/b: performs the check with shielding (polygon layers only) @/li
# @/ul

View File

@ -28,51 +28,51 @@ out = in.drc((width &lt; 2.0).polygons)
The following global functions are relevant for the DRC expressions:
</p><p>
<ul>
<li><a href="/about/drc_ref_global.xml#angle">global#angle</a> </li>
<li><a href="/about/drc_ref_global.xml#area">global#area</a> </li>
<li><a href="/about/drc_ref_global.xml#area_ratio">global#area_ratio</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_area_ratio">global#bbox_area_ratio</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_height">global#bbox_height</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_max">global#bbox_max</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_min">global#bbox_min</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_width">global#bbox_width</a> </li>
<li><a href="/about/drc_ref_global.xml#case">global#case</a> </li>
<li><a href="/about/drc_ref_global.xml#corners">global#corners</a> </li>
<li><a href="/about/drc_ref_global.xml#covering">global#covering</a> </li>
<li><a href="/about/drc_ref_global.xml#enc">global#enc</a> </li>
<li><a href="/about/drc_ref_global.xml#enclosing">global#enclosing</a> </li>
<li><a href="/about/drc_ref_global.xml#extent_refs">global#extent_refs</a> </li>
<li><a href="/about/drc_ref_global.xml#extents">global#extents</a> </li>
<li><a href="/about/drc_ref_global.xml#foreign">global#foreign</a> </li>
<li><a href="/about/drc_ref_global.xml#holes">global#holes</a> </li>
<li><a href="/about/drc_ref_global.xml#hulls">global#hulls</a> </li>
<li><a href="/about/drc_ref_global.xml#if_all">global#if_all</a> </li>
<li><a href="/about/drc_ref_global.xml#if_any">global#if_any</a> </li>
<li><a href="/about/drc_ref_global.xml#if_none">global#if_none</a> </li>
<li><a href="/about/drc_ref_global.xml#inside">global#inside</a> </li>
<li><a href="/about/drc_ref_global.xml#interacting">global#interacting</a> </li>
<li><a href="/about/drc_ref_global.xml#iso">global#iso</a> </li>
<li><a href="/about/drc_ref_global.xml#length">global#length</a> </li>
<li><a href="/about/drc_ref_global.xml#middle">global#middle</a> </li>
<li><a href="/about/drc_ref_global.xml#notch">global#notch</a> </li>
<li><a href="/about/drc_ref_global.xml#odd_polygons">global#odd_polygons</a> </li>
<li><a href="/about/drc_ref_global.xml#outside">global#outside</a> </li>
<li><a href="/about/drc_ref_global.xml#overlap">global#overlap</a> </li>
<li><a href="/about/drc_ref_global.xml#overlapping">global#overlapping</a> </li>
<li><a href="/about/drc_ref_global.xml#perimeter">global#perimeter</a> </li>
<li><a href="/about/drc_ref_global.xml#primary">global#primary</a> </li>
<li><a href="/about/drc_ref_global.xml#rectangles">global#rectangles</a> </li>
<li><a href="/about/drc_ref_global.xml#rectilinear">global#rectilinear</a> </li>
<li><a href="/about/drc_ref_global.xml#relative_height">global#relative_height</a> </li>
<li><a href="/about/drc_ref_global.xml#rounded_corners">global#rounded_corners</a> </li>
<li><a href="/about/drc_ref_global.xml#secondary">global#secondary</a> </li>
<li><a href="/about/drc_ref_global.xml#separation">global#separation</a> </li>
<li><a href="/about/drc_ref_global.xml#sep">global#sep</a> </li>
<li><a href="/about/drc_ref_global.xml#sized">global#sized</a> </li>
<li><a href="/about/drc_ref_global.xml#smoothed">global#smoothed</a> </li>
<li><a href="/about/drc_ref_global.xml#space">global#space</a> </li>
<li><a href="/about/drc_ref_global.xml#squares">global#squares</a> </li>
<li><a href="/about/drc_ref_global.xml#width">global#width</a> </li>
<li><a href="/about/drc_ref_global.xml#angle">angle</a> </li>
<li><a href="/about/drc_ref_global.xml#area">area</a> </li>
<li><a href="/about/drc_ref_global.xml#area_ratio">area_ratio</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_area_ratio">bbox_area_ratio</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_height">bbox_height</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_max">bbox_max</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_min">bbox_min</a> </li>
<li><a href="/about/drc_ref_global.xml#bbox_width">bbox_width</a> </li>
<li><a href="/about/drc_ref_global.xml#case">case</a> </li>
<li><a href="/about/drc_ref_global.xml#corners">corners</a> </li>
<li><a href="/about/drc_ref_global.xml#covering">covering</a> </li>
<li><a href="/about/drc_ref_global.xml#enc">enc</a> </li>
<li><a href="/about/drc_ref_global.xml#enclosing">enclosing</a> </li>
<li><a href="/about/drc_ref_global.xml#extent_refs">extent_refs</a> </li>
<li><a href="/about/drc_ref_global.xml#extents">extents</a> </li>
<li><a href="/about/drc_ref_global.xml#foreign">foreign</a> </li>
<li><a href="/about/drc_ref_global.xml#holes">holes</a> </li>
<li><a href="/about/drc_ref_global.xml#hulls">hulls</a> </li>
<li><a href="/about/drc_ref_global.xml#if_all">if_all</a> </li>
<li><a href="/about/drc_ref_global.xml#if_any">if_any</a> </li>
<li><a href="/about/drc_ref_global.xml#if_none">if_none</a> </li>
<li><a href="/about/drc_ref_global.xml#inside">inside</a> </li>
<li><a href="/about/drc_ref_global.xml#interacting">interacting</a> </li>
<li><a href="/about/drc_ref_global.xml#iso">iso</a> </li>
<li><a href="/about/drc_ref_global.xml#length">length</a> </li>
<li><a href="/about/drc_ref_global.xml#middle">middle</a> </li>
<li><a href="/about/drc_ref_global.xml#notch">notch</a> </li>
<li><a href="/about/drc_ref_global.xml#odd_polygons">odd_polygons</a> </li>
<li><a href="/about/drc_ref_global.xml#outside">outside</a> </li>
<li><a href="/about/drc_ref_global.xml#overlap">overlap</a> </li>
<li><a href="/about/drc_ref_global.xml#overlapping">overlapping</a> </li>
<li><a href="/about/drc_ref_global.xml#perimeter">perimeter</a> </li>
<li><a href="/about/drc_ref_global.xml#primary">primary</a> </li>
<li><a href="/about/drc_ref_global.xml#rectangles">rectangles</a> </li>
<li><a href="/about/drc_ref_global.xml#rectilinear">rectilinear</a> </li>
<li><a href="/about/drc_ref_global.xml#relative_height">relative_height</a> </li>
<li><a href="/about/drc_ref_global.xml#rounded_corners">rounded_corners</a> </li>
<li><a href="/about/drc_ref_global.xml#secondary">secondary</a> </li>
<li><a href="/about/drc_ref_global.xml#separation">separation</a> </li>
<li><a href="/about/drc_ref_global.xml#sep">sep</a> </li>
<li><a href="/about/drc_ref_global.xml#sized">sized</a> </li>
<li><a href="/about/drc_ref_global.xml#smoothed">smoothed</a> </li>
<li><a href="/about/drc_ref_global.xml#space">space</a> </li>
<li><a href="/about/drc_ref_global.xml#squares">squares</a> </li>
<li><a href="/about/drc_ref_global.xml#width">width</a> </li>
</ul>
</p><p>
The following documentation will list the methods available for DRC expression objects.
@ -237,6 +237,20 @@ out = in.drc(primary.area_ratio &gt; 3) # equivalent
The "area_ratio" method is available as a plain function or as a method on <a href="/about/drc_ref_drc#.xml">DRC#</a> expressions.
The plain function is equivalent to "primary.area_ratio".
</p>
<a name="area_sum"/><h2>"area_sum" - Selects the input polygons if the sum of all areas meets the condition</h2>
<keyword name="area_sum"/>
<p>Usage:</p>
<ul>
<li><tt>expression.area_sum (in condition)</tt></li>
</ul>
<p>
Returns the input polygons if the sum of their areas meets the specified
condition. This condition is evaluated on the total of all shapes generated in one step of the
"drc" loop. As there is a single primary in each loop iteration, "primary.area_sum" is
equivalent to "primary.area".
</p><p>
See <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> for more details about comparison specs.
</p>
<a name="bbox_aspect_ratio"/><h2>"bbox_aspect_ratio" - Selects the input polygon according to the aspect ratio of the bounding box</h2>
<keyword name="bbox_aspect_ratio"/>
<p>Usage:</p>
@ -569,6 +583,19 @@ out = in.drc(primary.length &gt;= 1.um) # equivalent
The "length" method is available as a plain function or as a method on <a href="/about/drc_ref_drc.xml">DRC</a> expressions.
The plain function is equivalent to "primary.length".
</p>
<a name="length_sum"/><h2>"length_sum" - Selects the input edges if the sum of their lengths meets the condition</h2>
<keyword name="length_sum"/>
<p>Usage:</p>
<ul>
<li><tt>expression.length_sum (in condition)</tt></li>
</ul>
<p>
Returns the input edges if the sum of their lengths meets the specified
condition. This condition is evaluated on the total of all edges generated in one step of the
"drc" loop.
</p><p>
See <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> for more details about comparison specs.
</p>
<a name="merged"/><h2>"merged" - Returns the merged input polygons, optionally selecting multi-overlap</h2>
<keyword name="merged"/>
<p>Usage:</p>
@ -635,6 +662,20 @@ out = in.drc(primary.perimeter &lt; 10.0) # equivalent
The perimeter method is available as a plain function or as a method on <a href="/about/drc_ref_drc.xml">DRC</a> expressions.
The plain function is equivalent to "primary.perimeter".
</p>
<a name="perimeter_sum"/><h2>"perimeter_sum" - Selects the input polygons if the sum of all perimeters meets the condition</h2>
<keyword name="perimeter_sum"/>
<p>Usage:</p>
<ul>
<li><tt>expression.perimeter_sum (in condition)</tt></li>
</ul>
<p>
Returns the input polygons if the sum of their perimeters meets the specified
condition. This condition is evaluated on the total of all shapes generated in one step of the
"drc" loop. As there is a single primary in each loop iteration, "primary.perimeter_sum" is
equivalent to "primary.perimeter".
</p><p>
See <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> for more details about comparison specs.
</p>
<a name="polygons"/><h2>"polygons" - Converts the input shapes into polygons</h2>
<keyword name="polygons"/>
<p>Usage:</p>

View File

@ -165,32 +165,6 @@ The area_cap argument is the capacitance in Farad per square micrometer.
See <class_doc href="DeviceExtractorCapacitorWithBulk">DeviceExtractorCapacitorWithBulk</class_doc> for more details
about this extractor.
</p>
<a name="case"/><h2>"case" - A conditional selector for the "drc" universal DRC function</h2>
<keyword name="case"/>
<p>Usage:</p>
<ul>
<li><tt>case(...)</tt></li>
</ul>
<p>
This function provides a conditional selector for the "drc" function.
It is used this way:
</p><p>
<pre>
out = in.drc(case(c1, r1, c2, r2, ..., cn, rn)
out = in.drc(case(c1, r1, c2, r2, ..., cn, rn, rdef)
</pre>
</p><p>
This function will evaluate c1 which is a universal DRC expression (see <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a>).
If the result is not empty, "case" will evaluate and return r1. Otherwise it
will continue with c2 and the result of this expression is not empty it will
return r2. Otherwise it will continue with c3/r3 etc.
</p><p>
If an odd number of arguments is given, the last expression is evaluated if
none of the conditions c1..cn gives a non-empty result.
</p><p>
As a requirement, the result types of all r1..rn expressions and the rdef
needs to be the same - i.e. all need to render polygons or edges or edge pairs.
</p>
<a name="cell"/><h2>"cell" - Selects a cell for input on the default source</h2>
<keyword name="cell"/>
<p>Usage:</p>
@ -1460,6 +1434,32 @@ is equivalent to "layer.squares" (see <a href="/about/drc_ref_layer.xml#squares"
argument, "squares" represents the rectangles filter for primary shapes in
<a href="/about/drc_ref_drc.xml">DRC</a> expressions (see <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> and <a href="/about/drc_ref_drc.xml#squares">DRC#squares</a> for more details).
</p>
<a name="switch"/><h2>"switch" - A conditional selector for the "drc" universal DRC function</h2>
<keyword name="switch"/>
<p>Usage:</p>
<ul>
<li><tt>switch(...)</tt></li>
</ul>
<p>
This function provides a conditional selector for the "drc" function.
It is used this way:
</p><p>
<pre>
out = in.drc(switch(c1, r1, c2, r2, ..., cn, rn)
out = in.drc(switch(c1, r1, c2, r2, ..., cn, rn, rdef)
</pre>
</p><p>
This function will evaluate c1 which is a universal DRC expression (see <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a>).
If the result is not empty, "switch" will evaluate and return r1. Otherwise it
will continue with c2 and the result of this expression is not empty it will
return r2. Otherwise it will continue with c3/r3 etc.
</p><p>
If an odd number of arguments is given, the last expression is evaluated if
none of the conditions c1..cn gives a non-empty result.
</p><p>
As a requirement, the result types of all r1..rn expressions and the rdef
needs to be the same - i.e. all need to render polygons or edges or edge pairs.
</p>
<a name="target"/><h2>"target" - Specify the target layout</h2>
<keyword name="target"/>
<p>Usage:</p>

View File

@ -332,41 +332,45 @@ improved performance in some applications and better readability.
</p><p>
The key concept for this method are DRC expressions. DRC expressions
are formed by using predefined keywords like "width", operators like "&amp;"
and method to build an abstract definition of the operations to perform
and methods to build an abstract definition of the operations to perform
within the DRC.
</p><p>
When the DRC function is executed, it will basically visit all shapes
from the input layer (the one, the "drc" method is called on), collect
the neighbor shapes from all involved other inputs and run the requested
operations on each cluster. Currently, "drc" is only available for polygon
layers.
from the input layer. This is the layer, the "drc" method is called on.
While it does, it collects the neighbor shapes from all involved other inputs
and runs the requested operations on each cluster.
Currently, "drc" is only available for polygon layers.
</p><p>
The nature of the "drc" operation is that of the loop over all (merged) input
This way, the nature of the "drc" operation is that of the loop over all (merged) input
polygons. Within the operation executed on each shape, it's possible to make
decisions such as "if the shape has an area larger than something, apply this
operation" etc. This can be achieved with conventional DRC functions too,
operation" or similar. This often can be achieved with conventional DRC functions too,
but involves potentially complex and heavy operations such as booleans, interact
etc. For this reason, the "drc" function may provide a performance benefit.
etc. For this reason, the "drc" function may provide a better performance.
</p><p>
In addition, within the loop, a single shape from the input layer is presented to
In addition, within the loop a single shape from the input layer is presented to
execution engine which runs the operations.
This allows using operations such as "size" without having to consider
neigbor polygons growing into the area of the initial shape. In this sense,
the "drc" function allows seeing the layer as individual polygons rather than
the "drc" function sees the layer as individual polygons rather than
a global "sea of polygons". This enables new applications which are otherwise
difficult to implement.
</p><p>
An important concept in the context of "drc" expressions is the "primary".
This expression represents a single primary shape. "Secondaries" are shapes
from other inputs. Primary shapes guide the operation - secondaries without
<h3>Primaries and secondaries </h3>
</p><p>
An important concept in "drc" expressions is the "primary".
The primary represents a single shape from the input layer. "Secondaries" are shapes
from other inputs. Primaries guide the operation - secondaries without
primaries are not seen. The "drc" operation will look for secondaries within
a certain distance which is determined from the operations within the
a certain distance which is determined from the operations from the
expression to execute. The secondaries collected in this step will not be
merged, so the secondary polygons may be partial. This is important when
using measurement operations like "area" on secondary polygons.
</p><p>
<h3>Checks </h3>
</p><p>
Here is an example for a generic DRC operation which performs a width
check for less than 0.5.um on the primary shapes. It uses the <a href="/about/drc_ref_global.xml#width">global#width</a> operator:
check for less than 0.5.um on the primary shapes. It uses the <a href="/about/drc_ref_global.xml#width">width</a> operator:
</p><p>
<pre>
out = in.drc(width &lt; 0.5.um)
@ -382,8 +386,8 @@ out = in.drc(width != 0.5.um)
out = in.drc(0.2.um &lt; width &lt; 0.5.um)
</pre>
</p><p>
To specify the second input for a two-layer check, specify the second input
with the check function. Here a two-layer separation check is used (<a href="/about/drc_ref_global.xml#separation">global#separation</a>):
To specify the second input for a two-layer check, specify it in brackets in
the check function. This example shows how to use a two-layer separation check (<a href="/about/drc_ref_global.xml#separation">separation</a>):
</p><p>
<pre>
l1 = input(1, 0)
@ -393,22 +397,113 @@ out = l1.drc(separation(l2) &lt; 0.5.um)
</p><p>
The second input of this check function can be a computed expression. In this
case the local loop will first evaluate the expression for the second input and
then use it inside the check.
then use the result for second input in the check. Note that this computation is
performed locally and separately for each primary and its context.
</p><p>
Options for the checks are also specified inside the brackets. For example,
to specify a projection metrics for width use:
to specify projection metrics ("projection") for width use:
</p><p>
<pre>
out = in.drc(width(projection) &lt; 0.5.um)
</pre>
</p><p>
The "drc" function supports filter operators. These select input or derived polygons
based on their properties. These filters are:
<h3>Edges and edge pairs </h3>
</p><p>
Although the "drc" function operates on polygon layers, internally it is
able to handle edge and edge pair types too. Some operations generate edge pairs,
some other generate edges. As results from one operation can be processed further
in the DRC expressions, methods are available to filter, process and convert
these types.
</p><p>
For example, all checks produce edge pairs which can be converted into polygons
using the "polygons" method:
</p><p>
<pre>
out = in.drc((width(projection) &lt; 0.5.um).polygons)
</pre>
</p><p>
Note a subtle detail: when putting the "polygons" method inside the "drc"
brackets, it is executed locally on every visited primary polygon. The result
in this case is identical to the global conversion:
</p><p>
<pre>
# same, but with "global" conversion:
out = in.drc(width(projection) &lt; 0.5.um).polygons
</pre>
</p><p>
But having the check polygons inside the loop opens new opportunities and
is more efficient in general. In the previous example, the local conversion
will keep a few edge pairs after having converted them to polygons. In
the global case, all edge pairs are collected first and then converted.
If there are many edge pairs, this requires more memory and a larger computing
overhead for managing the bigger number of shapes.
</p><p>
For the conversion of edges, edge pairs and polygons into other types, these
methods are provided:
</p><p>
<ul>
<li>"<a href="/about/drc_ref_global.xml#area">global#area</a>": select polygons based on their area </li>
<li>"<a href="/about/drc_ref_global.xml#perimeter">global#perimeter</a>": select polygons based on their perimeter </li>
<li>"<a href="/about/drc_ref_global.xml#bbox_min">global#bbox_min</a>", "<a href="/about/drc_ref_global.xml#bbox_max">global#bbox_max</a>", "<a href="/about/drc_ref_global.xml#bbox_width">global#bbox_width</a>", "<a href="/about/drc_ref_global.xml#bbox_height">global#bbox_height</a>": select polygons based on their bounding box properties </li>
<li><a href="/about/drc_ref_drc.xml#polygons:">DRC#polygons:</a> converts edge pairs to polygons </li>
<li><a href="/about/drc_ref_drc.xml#extended">DRC#extended</a>, <a href="/about/drc_ref_drc.xml#extended_in">DRC#extended_in</a>, <a href="/about/drc_ref_drc.xml#extended_out:">DRC#extended_out:</a> converts edges to polygons </li>
<li><a href="/about/drc_ref_drc.xml#first_edges">DRC#first_edges</a>, <a href="/about/drc_ref_drc.xml#second_edges:">DRC#second_edges:</a> extracts edges from edge pairs </li>
<li><a href="/about/drc_ref_drc.xml#edges:">DRC#edges:</a> decomposes edge pairs and polygons into edges </li>
<li><a href="/about/drc_ref_drc.xml#corners:">DRC#corners:</a> can extract corners from polygons </li>
</ul>
</p><p>
The following example decomposes the primary polygons into edges:
</p><p>
<pre>
out = in.drc(primary.edges)
</pre>
</p><p>
(for backward compatibility you cannot abbreviate "primary.edges" simply as "edges" like
other functions).
</p><p>
The previous example isn't quite exciting as it is equivalent to
</p><p>
<pre>
# Same as above
out = in.edges
</pre>
</p><p>
But it gets more interesting, as within the loop, "edges" delivers the edge set for
each individual polygon. It's possible to work with this distinct set, so for example
this will give you the edges of polygons with more than four corners:
</p><p>
<pre>
out = in.drc(primary.edges.count &gt; 4)
</pre>
</p><p>
Explanation: "count" is a "quantifier" which takes any kind of set (edges, edge pairs, polygons)
and returns the set if the number of inhabitants meets the given condition. Otherwise the set
is skipped. So it will look at the edges and if there are more than four (per primary shape),
it will forward this set.
</p><p>
The same result can be achieved with classic DRC with "interact" and a figure count, but
at a much higher computation cost.
</p><p>
<h3>Edge and edge/polygon operations </h3>
</p><p>
The "drc" framework supports the following edge and edge/polygon operations:
</p><p>
<ul>
<li>Edge vs. edge and edge vs. polygon booleans </li>
<li>Edge vs. polygon interactions (<a href="/about/drc_ref_drc.xml#interacting">DRC#interacting</a>, <a href="/about/drc_ref_drc.xml#overlapping">DRC#overlapping</a>) </li>
<li>Edge sampling (<a href="/about/drc_ref_drc.xml#start_segments">DRC#start_segments</a>, <a href="/about/drc_ref_drc.xml#centers">DRC#centers</a>, <a href="/about/drc_ref_drc.xml#end_segments">DRC#end_segments</a>) </li>
</ul>
</p><p>
<h3>Filters </h3>
</p><p>
Filter operators select input polygons or edges based on their properties. These filters are provided:
</p><p>
<ul>
<li>"<a href="/about/drc_ref_drc.xml#area">DRC#area</a>": selects polygons based on their area </li>
<li>"<a href="/about/drc_ref_drc.xml#perimeter">DRC#perimeter</a>": selects polygons based on their perimeter </li>
<li>"<a href="/about/drc_ref_drc.xml#area_ratio">DRC#area_ratio</a>": selects polygons based on their bounding box to polygon area ratio </li>
<li>"<a href="/about/drc_ref_drc.xml#bbox_aspect_ratio">DRC#bbox_aspect_ratio</a>": selects polygons based on their bounding box aspect ratio </li>
<li>"<a href="/about/drc_ref_drc.xml#relative_height">DRC#relative_height</a>": selects polygons based on their relative height </li>
<li>"<a href="/about/drc_ref_drc.xml#bbox_min">DRC#bbox_min</a>", "<a href="/about/drc_ref_global.xml#bbox_max">bbox_max</a>", "<a href="/about/drc_ref_global.xml#bbox_width">bbox_width</a>", "<a href="/about/drc_ref_global.xml#bbox_height">bbox_height</a>": selects polygons based on their bounding box properties </li>
<li>"<a href="/about/drc_ref_drc.xml#length">DRC#length</a>": selects edges based on their length </li>
<li>"<a href="/about/drc_ref_drc.xml#angle">DRC#angle</a>": selects edges based on their orientation </li>
</ul>
</p><p>
For example, to select polygons with an area larger than one square micrometer, use:
@ -431,27 +526,33 @@ In the same fashion, "perimeter" applies to the perimeter of the polygon.
"bbox_min" etc. will evaluate a particular dimensions of the polygon's bounding box and
use the respective dimension for filtering the polygon.
</p><p>
Note that it's basically possible to use the polygon filters on any kind of input.
In fact, plain "area" for example is a shortcut for "<a href="/about/drc_ref_global.xml#primary">global#primary</a>.area" indicating that
Note that it's basically possible to use the polygon filters on any input - computed and secondaries.
In fact, plain "area" for example is a shortcut for "<a href="/about/drc_ref_global.xml#primary">primary</a>.area" indicating that
the area of primary shapes are supposed to be computed.
However, any input other than the primary is not necessarily complete or it may
consist of multiple polygons. Hence the computed values may be too big or too small.
It's recommended therefore to use the measurement functions on primary polygons
only.
unless you know what you're doing.
</p><p>
<h3>Filter predicates </h3>
</p><p>
The "drc" feature also supports some predicates. "predicates" are boolean values
indicating a certain condition. A predicate filter works in a way that it only
passes the polygons
passes the polygons if the condition is met.
</p><p>
The predicates available currently are:
</p><p>
<ul>
<li>"<a href="/about/drc_ref_global.xml#rectangles">global#rectangles</a>": Filters rectangles </li>
<li>"<a href="/about/drc_ref_global.xml#rectilinear">global#rectilinear</a>": Filters rectilinear ("Manhattan") polygons </li>
<li>"<a href="/about/drc_ref_global.xml#rectangles">rectangles</a>": Filters rectangles </li>
<li>"<a href="/about/drc_ref_global.xml#squares">squares</a>": Filters squares </li>
<li>"<a href="/about/drc_ref_global.xml#rectilinear">rectilinear</a>": Filters rectilinear ("Manhattan") polygons </li>
</ul>
</p><p>
For the same reason as explained above, it's recommended to use these predicates
standalone, so they act on primary shapes. It's possible to use the predicates
on computed shapes or secondary input, but that may not render the desired results.
on computed shapes or secondaries, but that may not render the desired results.
</p><p>
<h3>Logical NOT operator </h3>
</p><p>
The "!" operator will evaluate the expression behind it and return the
current primary shape if the input is empty and return an empty polygon set
@ -462,36 +563,57 @@ not rectangles:
out = in.drc(! rectangles)
</pre>
</p><p>
The logical "if_any" or "if_all" statements allow connecting multiple
<h3>Logical combination operators </h3>
</p><p>
The logical "if_any" or "if_all" functions allow connecting multiple
conditions and evaluate to "true" (means: a non-empty shape set) if either
on input is a non-empty shape set ("if_any") or if all inputs are non-empty
("if_all"). For example, this will select all polygons which are rectangles
one input is a non-empty shape set ("if_any") or if all inputs are non-empty
("if_all").
</p><p>
For example, this will select all polygons which are rectangles
and whose area is larger than 20 quare micrometers:
</p><p>
<pre>
out = in.drc(if_all(rectangles, area &gt; 20.0))
</pre>
</p><p>
In fact, "if_all" renders the result of the last expression, provided all
previous ones are non-empty. So this operation will render rectangles
sized by 100 nm and skip all other types of polygons:
"if_all" delivers the primary shape if all of the input expressions
render a non-empty result.
</p><p>
In contrast to this, the "if_any" operation will deliver the primary shape
if one of the input expressions renders a non-empty result.
</p><p>
The "<a href="/about/drc_ref_global.xml#switch">switch</a>" function allows selecting one input based on the results of an
expression. In the two-input form it's equivalent to "if". The first expression
is the condition. If it evaluates to a non-empty shape set, the result of the
second expression is taken. Otherwise, the result is empty.
</p><p>
Hence the following code delivers all rectangles sized by 100 nm. All
other shapes are skipped:
</p><p>
<pre>
out = in.drc(if_all(rectangles, sized(100.nm)))
out = in.drc(switch(rectangles, primary.sized(100.nm)))
</pre>
</p><p>
Contrary to this, the "if_any" operation will render the first non-empty
expression result and skip the following ones. So this example will
size all rectangles by 100 nm and leave all other types of polygons
untouched:
A third expression will be considered the "else" branch: the result of
this expression will be taken if the first one is not taken. So this
example will size all rectangles and leave other shapes untouched:
</p><p>
<pre>
out = in.drc(if_any(rectangles.sized(100.nm), primary))
out = in.drc(switch(rectangles, primary.sized(100.nm), primary))
</pre>
</p><p>
If more expressions are given, they are considered as a sequence of condition/result
chain (c1, e1, c2, e2, ...) in the sense of "if(c1) return(e1) else if(c2) return(e2) ...".
So the e1 is taken if c1 is met, e2 is taken when c1 is not met, but c2 is and so forth.
If there is an odd number of expressions, the last one will be the default expression
which is taken if none of the conditions is met.
</p><p>
<h3>Polygon manipulations </h3>
</p><p>
The "drc" operations feature polygon manipulations where the input is
either the primary polygon or derived shapes.
Manipulations include sizing ("<a href="/about/drc_ref_global.xml#sized">global#sized</a>"), corner rounding ("<a href="/about/drc_ref_global.xml#rounded_corners">global#rounded_corners</a>"), smoothing ("<a href="/about/drc_ref_global.xml#smoothed">global#smoothed</a>")
either the primary, secondaries or derived shapes.
Manipulations include sizing ("<a href="/about/drc_ref_global.xml#sized">sized</a>"), corner rounding ("<a href="/about/drc_ref_global.xml#rounded_corners">rounded_corners</a>"), smoothing ("<a href="/about/drc_ref_global.xml#smoothed">smoothed</a>")
and boolean operations.
</p><p>
This example computes a boolean AND between two layers before selecting
@ -515,13 +637,40 @@ Note that the precise form of the example above is
out = l1.drc((primary &amp; secondary(l2)).area &gt; 1.0)
</pre>
</p><p>
The "<a href="/about/drc_ref_global.xml#secondar">global#secondar</a>" operator indicates that "l2" is to be used as secondary input to the "drc" function. Only
The "<a href="/about/drc_ref_global.xml#secondary">secondary</a>" operator indicates that "l2" is to be used as secondary input to the "drc" function. Only
in this form, the operators of the boolean AND can be reversed:
</p><p>
<pre>
out = l1.drc((secondary(l2) &amp; primary).area &gt; 1.0)
</pre>
</p><p>
<h3>Quantifiers </h3>
</p><p>
Some filters operate on properties of the full, local, per-primary shape set.
While the loop is executed, the DRC expressions will collect shapes, either
from the primary, it's neighborhood (secondaries) or from deriving shape sets.
</p><p>
Obviously the primary is a simple one: it consists of a single shape, because
this is how the loop operates. Derived shape sets however can be more complex.
"Quantifiers" allow assessing properties of the complete, per-primary shape
set. A simple one is "<a href="/about/drc_ref_drc.xml#count">DRC#count</a>" which checks if the number of shapes within
a shape set is within a given range.
</p><p>
Obviously, "primary.count == 1" is always true. So using "count" primaries isn't
much fun. So it's better to use it on derived sets.
The following condition will select all primary shapes which have more than 13 corners:
</p><p>
<pre>
out = in.drc(if_any(primary.corners.count &gt; 13))
</pre>
</p><p>
Note an important detail here: the "if_any" function will make this statement render primary
polygons, if the expression inside gives a non-empty result. Without
"if_any", the result would be the output of "count" which is the set of all
corners where the corner count is larger than 13.
</p><p>
<h3>Expressions as objects </h3>
</p><p>
The expression inside the "drc" function is a Ruby object and can be
stored in variables. If you need the same expression multiple times, it can be
more efficient to use the same Ruby object. In this example, the same expression
@ -539,31 +688,15 @@ out = l1.drc((overlap_area == 1.0) + (overlap_area == 2.0))
</pre>
</p><p>
Note that the first line prepares the operation, but does not execute the area computation
or the boolean operation. But when the "drc" function executes the operation it will
only compute the area once as it is represented by the same Ruby object.
or the boolean operation. But when the "drc" function executes the loop over the primaries it will
only compute the area once per primary as it is represented by the same Ruby object.
</p><p>
The "drc" functionality also offers support for edge pairs and edges. Edge pairs
are the results of check operations and can be turned into polygons using the
"polygons" method:
<h3>Outlook </h3>
</p><p>
<pre>
drc = in.drc((width &lt; 0.5.um).polygons)
</pre>
DRC expressions are quite rich and powerful. They provide a more intuitive way of
writing DRC expressions, are more efficient and open new opportunities. DRC
development is likely to focus on this scheme in the future.
</p><p>
Similarly, polygons can be converted into edges:
</p><p>
<pre>
drc = in.drc(primary.edges)
</pre>
</p><p>
The "drc" framework supports edge vs. edge and edge vs. polygon booleans, edge
filters (<a href="/about/drc_ref_global.xml#length">global#length</a>, <a href="/about/drc_ref_global.xml#angle">global#angle</a>), edge vs. polygon interactions (<a href="/about/drc_ref_global.xml#interacting">global#interacting</a>, <a href="/about/drc_ref_global.xml#overlapping">global#overlapping</a>),
edge sampling (<a href="/about/drc_ref_global.xml#start_segments">global#start_segments</a>, <a href="/about/drc_ref_global.xml#centers">global#centers</a>, <a href="/about/drc_ref_global.xml#end_segments">global#end_segments</a>) and edge to polygon
conversions (<a href="/about/drc_ref_global.xml#extended">global#extended</a>, <a href="/about/drc_ref_global.xml#extended_in">global#extended_in</a>, <a href="/about/drc_ref_global.xml#extended_out">global#extended_out</a>). Edge pairs
can be converted into polygons and edges and separated into first and second edges (<a href="/about/drc_ref_global.xml#first_edges">global#first_edges</a>,
<a href="/about/drc_ref_global.xml#second_edges">global#second_edges</a>).
</p><p>
The bottom line is: DRC expressions are quite rich and there is a lot more to be said and written.
More formal details about the bits and pieces can be found in the <a href="/about/drc_ref_drc.xml">DRC</a> class documentation.
</p>
<a name="dup"/><h2>"dup" - Duplicates a layer</h2>
@ -1014,10 +1147,10 @@ The following image shows the effect of the "in" method (input1: red, input2: bl
<p>
Objects that can be inserted are <class_doc href="Edge">Edge</class_doc> objects (into edge layers) or
<class_doc href="DPolygon">DPolygon</class_doc>, <class_doc href="DSimplePolygon">DSimplePolygon</class_doc>, <class_doc href="Path">Path</class_doc>, <class_doc href="DBox">DBox</class_doc> (into polygon layers).
Convenience methods exist to create such objects (<a href="/about/drc_ref_global.xml#edge">global#edge</a>, <a href="/about/drc_ref_global.xml#polygon">global#polygon</a>, <a href="/about/drc_ref_global.xml#box">global#box</a> and <a href="/about/drc_ref_#global.xml#path">#global#path</a>).
Convenience methods exist to create such objects (<a href="/about/drc_ref_global.xml#edge">edge</a>, <a href="/about/drc_ref_global.xml#polygon">polygon</a>, <a href="/about/drc_ref_global.xml#box">box</a> and <a href="/about/drc_ref_#global.xml#path">#global#path</a>).
However, RBA constructors can used as well.
</p><p>
The insert method is useful in combination with the <a href="/about/drc_ref_global.xml#polygon_layer">global#polygon_layer</a> or <a href="/about/drc_ref_global.xml#edge_layer">global#edge_layer</a> functions:
The insert method is useful in combination with the <a href="/about/drc_ref_global.xml#polygon_layer">polygon_layer</a> or <a href="/about/drc_ref_global.xml#edge_layer">edge_layer</a> functions:
</p><p>
<pre>
el = edge_layer
@ -1683,7 +1816,7 @@ one to three parameters: a layer number, a data type (optional, default is 0)
and a layer name (optional). Alternatively, the output can be specified by
a single <class_doc href="LayerInfo">LayerInfo</class_doc> object.
</p><p>
See <a href="/about/drc_ref_global.xml#report">global#report</a> and <a href="/about/drc_ref_global.xml#target">global#target</a> on how to configure output to a target layout
See <a href="/about/drc_ref_global.xml#report">report</a> and <a href="/about/drc_ref_global.xml#target">target</a> on how to configure output to a target layout
or report database.
</p>
<a name="outside"/><h2>"outside" - Selects shapes or regions of self which are outside the other region</h2>
@ -2689,7 +2822,7 @@ each other is more or equal than min and less than max </li>
<li><b>projecting (in condition) </b>: This specification is equivalent to "projection_limits"
but is more intuitive, as "projecting" is written with a condition, like
"projecting &lt; 2.um". Available operators are: "==", "&lt;", "&lt;=", "&gt;" and "&gt;=".
Double-bounded ranges are also available, like: "0.5 &lt;= projecting &lt; 2.0".
Double-bounded ranges are also available, like: "0.5 &lt;= projecting &lt; 2.0". </li>
<li><b>transparent </b>: performs the check without shielding (polygon layers only) </li>
<li><b>shielded </b>: performs the check with shielding (polygon layers only) </li>
</ul>

View File

@ -281,7 +281,7 @@ form, the extractor object is given. In the second form, the extractor's
class object and the new extractor's name is given.
</p><p>
The device extractor is either an instance of one of the predefined extractor
classes (e.g. obtained from the utility methods such as <a href="/about/drc_ref_global.xml#mos4">global#mos4</a>) or a custom class.
classes (e.g. obtained from the utility methods such as <a href="/about/drc_ref_global.xml#mos4">mos4</a>) or a custom class.
It provides the
algorithms for deriving the device parameters from the device geometry. It needs
several device recognition layers which are passed in the layer hash.
@ -289,17 +289,17 @@ several device recognition layers which are passed in the layer hash.
Predefined device extractors are:
</p><p>
<ul>
<li><a href="/about/drc_ref_global.xml#mos3">global#mos3</a> - A three-terminal MOS transistor </li>
<li><a href="/about/drc_ref_global.xml#mos4">global#mos4</a> - A four-terminal MOS transistor </li>
<li><a href="/about/drc_ref_global.xml#dmos3">global#dmos3</a> - A three-terminal MOS asymmetric transistor </li>
<li><a href="/about/drc_ref_global.xml#dmos4">global#dmos4</a> - A four-terminal MOS asymmetric transistor </li>
<li><a href="/about/drc_ref_global.xml#bjt3">global#bjt3</a> - A three-terminal bipolar transistor </li>
<li><a href="/about/drc_ref_global.xml#bjt4">global#bjt4</a> - A four-terminal bipolar transistor </li>
<li><a href="/about/drc_ref_global.xml#diode">global#diode</a> - A planar diode </li>
<li><a href="/about/drc_ref_global.xml#resistor">global#resistor</a> - A resistor </li>
<li><a href="/about/drc_ref_global.xml#resistor_with_bulk">global#resistor_with_bulk</a> - A resistor with a separate bulk terminal </li>
<li><a href="/about/drc_ref_global.xml#capacitor">global#capacitor</a> - A capacitor </li>
<li><a href="/about/drc_ref_global.xml#capacitor_with_bulk">global#capacitor_with_bulk</a> - A capacitor with a separate bulk terminal </li>
<li><a href="/about/drc_ref_global.xml#mos3">mos3</a> - A three-terminal MOS transistor </li>
<li><a href="/about/drc_ref_global.xml#mos4">mos4</a> - A four-terminal MOS transistor </li>
<li><a href="/about/drc_ref_global.xml#dmos3">dmos3</a> - A three-terminal MOS asymmetric transistor </li>
<li><a href="/about/drc_ref_global.xml#dmos4">dmos4</a> - A four-terminal MOS asymmetric transistor </li>
<li><a href="/about/drc_ref_global.xml#bjt3">bjt3</a> - A three-terminal bipolar transistor </li>
<li><a href="/about/drc_ref_global.xml#bjt4">bjt4</a> - A four-terminal bipolar transistor </li>
<li><a href="/about/drc_ref_global.xml#diode">diode</a> - A planar diode </li>
<li><a href="/about/drc_ref_global.xml#resistor">resistor</a> - A resistor </li>
<li><a href="/about/drc_ref_global.xml#resistor_with_bulk">resistor_with_bulk</a> - A resistor with a separate bulk terminal </li>
<li><a href="/about/drc_ref_global.xml#capacitor">capacitor</a> - A capacitor </li>
<li><a href="/about/drc_ref_global.xml#capacitor_with_bulk">capacitor_with_bulk</a> - A capacitor with a separate bulk terminal </li>
</ul>
</p><p>
Each device class (e.g. n-MOS/p-MOS or high Vt/low Vt) needs its own instance

View File

@ -19,7 +19,7 @@ The LVS Netter object inherits all methods of the <a href="/about/drc_ref_netter
</p><p>
An individual netter object can be created, if the netter results
need to be kept for multiple extractions. If you really need
a Netter object, use the global <a href="/about/lvs_ref_global.xml#netter">global#netter</a> function:
a Netter object, use the global <a href="/about/lvs_ref_global.xml#netter">netter</a> function:
</p><p>
<pre>
# create a new Netter object: