mirror of https://github.com/KLayout/klayout.git
Rename some functions, DRC binding for 'evaluate_nets'
This commit is contained in:
parent
61aa08cd64
commit
73681755ed
|
|
@ -216,7 +216,7 @@ static db::Region antenna_check (db::LayoutToNetlist *l2n, const db::Region &pol
|
|||
return antenna_check3 (l2n, poly, 1, 0, metal, 1, 0, ratio, diodes, texts);
|
||||
}
|
||||
|
||||
static db::Region measure_net (db::LayoutToNetlist *l2n, const db::Region &primary, const std::map<std::string, const db::Region *> &secondary, const std::string &expression, const tl::Variant &variables)
|
||||
static db::Region evaluate_nets (db::LayoutToNetlist *l2n, const db::Region &primary, const std::map<std::string, const db::Region *> &secondary, const std::string &expression, const tl::Variant &variables)
|
||||
{
|
||||
if (! variables.is_array ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'variables' argument needs to a hash")));
|
||||
|
|
@ -1224,7 +1224,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
"\n"
|
||||
"This variant has been introduced in version 0.26.6.\n"
|
||||
) +
|
||||
gsi::method_ext ("measure_net", &measure_net, gsi::arg ("primary"), gsi::arg ("secondary"), gsi::arg ("expression"), gsi::arg ("variables", std::map<std::string, tl::Variant> (), "{}"),
|
||||
gsi::method_ext ("evaluate_nets", &evaluate_nets, gsi::arg ("primary"), gsi::arg ("secondary"), gsi::arg ("expression"), gsi::arg ("variables", std::map<std::string, tl::Variant> (), "{}"),
|
||||
"@brief Runs a generic net measurement function\n"
|
||||
"\n"
|
||||
"This method accepts some primary layer, a number of secondary layers with names and an expression.\n"
|
||||
|
|
|
|||
|
|
@ -2437,6 +2437,12 @@ CODE
|
|||
# @synopsis antenna_check(gate, metal, ratio, [ diode_specs ... ])
|
||||
# See \Netter#antenna_check for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name evaluate_nets
|
||||
# @brief Evaluates expressions on nets
|
||||
# @synopsis evaluate_nets(primary_layer, secondary_layers, expression [, variables])
|
||||
# See \Netter#evaluate_nets for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name l2n_data
|
||||
# @brief Gets the internal RBA::LayoutToNetlist object for the default \Netter
|
||||
|
|
@ -2489,6 +2495,7 @@ CODE
|
|||
|
||||
%w(
|
||||
antenna_check
|
||||
evaluate_nets
|
||||
clear_connections
|
||||
connect
|
||||
connect_global
|
||||
|
|
|
|||
|
|
@ -5762,36 +5762,36 @@ END
|
|||
other.is_a?(DRCLayer) || raise("Argument needs to be a DRC layer")
|
||||
end
|
||||
|
||||
def requires_region
|
||||
self.data.is_a?(RBA::Region) || raise("Requires a polygon layer")
|
||||
def requires_region(name = nil)
|
||||
self.data.is_a?(RBA::Region) || raise(name ? "#{name} requires a polygon layer" : "Requires a polygon layer")
|
||||
end
|
||||
|
||||
def requires_texts_or_region
|
||||
self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Texts) || raise("Requires a polygon or text layer")
|
||||
def requires_texts_or_region(name = nil)
|
||||
self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Texts) || raise(name ? "#{name} requires a polygon or text layer" : "Requires a polygon or text layer")
|
||||
end
|
||||
|
||||
def requires_texts
|
||||
self.data.is_a?(RBA::Texts) || raise("Requires a text layer")
|
||||
def requires_texts(name = nil)
|
||||
self.data.is_a?(RBA::Texts) || raise(name ? "#{name} requires a text layer" : "Requires a text layer")
|
||||
end
|
||||
|
||||
def requires_edge_pairs
|
||||
self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge pair layer")
|
||||
def requires_edge_pairs(name = nil)
|
||||
self.data.is_a?(RBA::EdgePairs) || raise(name ? "#{name} requires an edge pair layer" : "Requires an edge pair layer")
|
||||
end
|
||||
|
||||
def requires_edges
|
||||
self.data.is_a?(RBA::Edges) || raise("Requires an edge layer")
|
||||
def requires_edges(name = nil)
|
||||
self.data.is_a?(RBA::Edges) || raise(name ? "#{name} requires an edge layer" : "Requires an edge layer")
|
||||
end
|
||||
|
||||
def requires_edges_or_edge_pairs
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge or edge pair layer")
|
||||
def requires_edges_or_edge_pairs(name = nil)
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) || raise(name ? "#{name} requires an edge or edge pair layer" : "Requires an edge or edge pair layer")
|
||||
end
|
||||
|
||||
def requires_edges_or_region
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || raise("Requires an edge or polygon layer")
|
||||
def requires_edges_or_region(name = nil)
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || raise(name ? "#{name} requires an edge or polygon layer" : "Requires an edge or polygon layer")
|
||||
end
|
||||
|
||||
def requires_edges_texts_or_region
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Texts) || raise("Requires an edge, text or polygon layer")
|
||||
def requires_edges_texts_or_region(name = nil)
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Texts) || raise(name ? "#{name} requires an edge, text or polygon layer" : "Requires an edge, text or polygon layer")
|
||||
end
|
||||
|
||||
def requires_same_type(other)
|
||||
|
|
|
|||
|
|
@ -769,6 +769,90 @@ module DRC
|
|||
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name evaluate_nets
|
||||
# @brief Evaluates net properties and annotates shapes from a given layer on the nets
|
||||
# @synopsis evaluate_nets(primary_layer, secondary_layers, expression [, variables])
|
||||
#
|
||||
# The function takes a primary layer and a number of secondary layers, each of
|
||||
# them given a variable name.
|
||||
# It visits each net and evaluates the given expression on the net.
|
||||
# The expression needs to be written in KLayout expression notations.
|
||||
#
|
||||
# By default, the shapes of the primary layer are copied to the output.
|
||||
#
|
||||
# Using the "put" function inside the expression, properties can be
|
||||
# attached to the output shapes. The properties can be computed using
|
||||
# a number of net attributes - area and perimeter, but also the RBA::Net
|
||||
# object representing the net. This allows implementing a more elaborate
|
||||
# antenna check for example.
|
||||
#
|
||||
# Also, the expression can choose to drop shapes and not copy then to
|
||||
# the output by calling the "skip" function with a "true" argument.
|
||||
#
|
||||
# Arbitrary values can be passed as variables, which removes the need
|
||||
# to encode variable values into the expression.
|
||||
#
|
||||
# The following functions are available
|
||||
#
|
||||
# @ul
|
||||
# @li "net" - the RBA::Net object of the current net
|
||||
# @li "skip(flag)" - if called with a 'true' argument, the primary layer's shapes are not copied for this net
|
||||
# @li "put(name, value)" - places the value as a property with name 'name' (this must be a string) on the output shapes
|
||||
# @li "area" - the combined area of the primary layer's shapes on the net in square micrometer units
|
||||
# @li "area(symbol)" - the combined area of the secondary layer's shapes on the net in square micrometer units
|
||||
# @li "perimeter" - the perimeter of the primary layer's shapes on the net in micrometer units
|
||||
# @li "perimeter(symbol)" - the perimeter of the secondary layer's shapes on the net in micrometer units
|
||||
# @/ul
|
||||
#
|
||||
# Here, 'symbol' is the name given to the secondary layer in the secondary layer
|
||||
# dictionary.
|
||||
#
|
||||
# The following example computes the area ratio of metal vs. gate area and
|
||||
# attaches the value on a property with name 'AR' to the shapes of a copy of the
|
||||
# 'gate' layer:
|
||||
#
|
||||
# @code
|
||||
# gate = ... # a layer with the gate shapes
|
||||
# metal = ... # a layer with metal shapes
|
||||
#
|
||||
# # NOTE: 'MET' is the name we are going to use in the expression
|
||||
# antenna_errors = evaluate_nets(gate, { "MET" => metal }, "put('AR',area(MET)/area)")
|
||||
# @/code
|
||||
#
|
||||
# The following example computes the area ratio of metal vs. gate area and
|
||||
# outputs the gate shapes of all nets whose metal to gate area ratio is bigger than
|
||||
# 500. The area ratio is output to a property with name 'AR':
|
||||
#
|
||||
# @code
|
||||
# gate = ... # a layer with the gate shapes
|
||||
# metal = ... # a layer with metal shapes
|
||||
#
|
||||
# variables = { "thr" => 500.0 }
|
||||
# expression = "var ar=area(MET)/area; put('AR',ar); skip(ar<thr)"
|
||||
#
|
||||
# antenna_errors = evaluate_nets(gate, { "MET" => metal }, expression, variables)
|
||||
# @/code
|
||||
|
||||
def evaluate_nets(primary, secondary, expression, variables = {})
|
||||
|
||||
primary.is_a?(DRC::DRCLayer) || raise("First argument must be a layer")
|
||||
primary.requires_region("'primary'")
|
||||
|
||||
secondary_data = {}
|
||||
secondary.is_a?(Hash) || raise("Second argument must be a hash of names and layers")
|
||||
secondary.each do |k,v|
|
||||
v.is_a?(DRC::DRCLayer) || raise("Second argument must be a hash of names and polygon")
|
||||
v.requires_region("Secondary '#{k}'")
|
||||
secondary_data[k.to_s] = v.data
|
||||
end
|
||||
|
||||
expression.is_a?(String) || raise("'expression' argument must be a string")
|
||||
|
||||
DRC::DRCLayer::new(@engine, @engine._cmd(l2n_data, :evaluate_nets, primary.data, secondary_data, expression, variables))
|
||||
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name l2n_data
|
||||
# @brief Gets the internal RBA::LayoutToNetlist object
|
||||
|
|
|
|||
|
|
@ -2013,3 +2013,14 @@ TEST(141d_merge_properties)
|
|||
{
|
||||
run_test (_this, "141", true);
|
||||
}
|
||||
|
||||
TEST(142_evaluate_nets)
|
||||
{
|
||||
run_test (_this, "142", false);
|
||||
}
|
||||
|
||||
TEST(142d_evaluate_nets)
|
||||
{
|
||||
run_test (_this, "142", true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
source $drc_test_source
|
||||
target $drc_test_target
|
||||
|
||||
if $drc_test_deep
|
||||
deep
|
||||
end
|
||||
|
||||
l1 = input(1, 0)
|
||||
l2 = input(2, 0)
|
||||
l3 = input(3, 0)
|
||||
l4 = input(4, 0)
|
||||
l5 = input(5, 0)
|
||||
|
||||
connect(l1, l2)
|
||||
connect(l2, l3)
|
||||
connect(l3, l4)
|
||||
connect(l4, l5)
|
||||
|
||||
l1_measured = evaluate_nets(l1, { "l2" => l2, "l3" => l3, "l4" => l4, "l5" => l5}, "put(5, area(l5)); put(0, area); put(100, area(l5)/area)")
|
||||
|
||||
l1.output(1, 0)
|
||||
l2.output(2, 0)
|
||||
l3.output(3, 0)
|
||||
l4.output(4, 0)
|
||||
l5.output(5, 0)
|
||||
|
||||
l1_measured.output(100, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue