FEATURE: 'labels' method in DRC scripts allows copying labels to output layers.

This commit is contained in:
Matthias Koefferlein 2018-04-28 10:36:13 +02:00
parent 86aea962c9
commit ccfe6fa918
10 changed files with 150 additions and 50 deletions

View File

@ -1,5 +1,8 @@
0.25.3 0.25.3
* Enhancement: Pass label (text) layers through DRC script
The "labels" method now allows copying labels from a layer
to the output.
* Enhancement: New "split" method for polygons * Enhancement: New "split" method for polygons
This method will fragment the polygons into two or more This method will fragment the polygons into two or more
smaller parts for reducing their vertex count. smaller parts for reducing their vertex count.

View File

@ -4,7 +4,7 @@
def run_demo(gen, cmd, out) def run_demo(gen, cmd, out)
img_path = "src/lay/doc/images" img_path = "src/lay/lay/doc/images"
mw = RBA::Application::instance::main_window mw = RBA::Application::instance::main_window

View File

@ -3,9 +3,9 @@
$script_call = $0 + " " + ARGV.join(" ") $script_call = $0 + " " + ARGV.join(" ")
$key="%DRC%" $key="%DRC%"
$infile="src/lay/built_in_macros/drc.lym" $infile="src/drc/drc/built-in-macros/drc.lym"
$loc = "about/drc_ref" $loc = "about/drc_ref"
$outfiles="src/lay/doc" $outfiles="src/lay/lay/doc"
$title="DRC Reference" $title="DRC Reference"
def create_ref(s) def create_ref(s)

View File

@ -3469,6 +3469,67 @@ CODE
# @/ul # @/ul
def input(*args) def input(*args)
layers = parse_input_layers(*args)
DRCLayer::new(@engine, @engine._cmd(@engine, :_input, @layout_var, @cell.cell_index, layers, @sel, @box, @clip, @overlapping, false))
end
# %DRC%
# @name labels
# @brief Gets the labels (texts) from an input layer
# @synopsis source.labels(layer)
# @synopsis source.labels(layer, datatype)
# @synopsis source.labels(layer_into)
# @synopsis source.labels(filter, ...)
# Creates a layer with the labels from the given layer of the source.
# The layer can be specified by layer and optionally datatype, by a RBA::LayerInfo
# object or by a sequence of filters.
# Filters are expressions describing ranges
# of layers and/or datatype numbers or layer names. Multiple filters
# can be given and all layers matching at least one of these filter
# expressions are joined to render the label collection. See "input" for
# more details about the input layer specification.
#
# Label layers currently can only be passed to an output layer.
# Processing of labels is not supported. See "texts" for a way to filter
# texts and use the text locations in geometrical operations.
#
# @code
# labels(1, 0).output(100, 0)
# @/code
def labels(*args)
layers = parse_input_layers(*args)
DRCLayer::new(@engine, @engine._cmd(@engine, :_input, @layout_var, @cell.cell_index, layers, @sel, @box, @clip, @overlapping, true))
end
# %DRC%
# @name layers
# @brief Gets the layers the source contains
# @synopsis source.layers
# Delivers a list of RBA::LayerInfo objects representing the layers
# inside the source.
#
# One application is to read all layers from a source. In the following
# example, the "and" operation is used to perform a clip with the given
# rectangle. Note that this solution is not efficient - it's provided
# as an example only:
#
# @code
# output_cell("Clipped")
#
# clip_box = polygon_layer
# clip_box.insert(box(0.um, -4.um, 4.um, 0.um))
#
# layers.each { |l| (input(l) & clip_box).output(l) }
# @/code
def layers
@layout.layer_indices.collect { |li| @layout.get_info(li) }
end
private
def parse_input_layers(*args)
layers = [] layers = []
@ -3505,35 +3566,10 @@ CODE
end end
DRCLayer::new(@engine, @engine._cmd(@engine, :_input, @layout_var, @cell.cell_index, layers, @sel, @box, @clip, @overlapping)) layers
end end
# %DRC%
# @name layers
# @brief Gets the layers the source contains
# @synopsis source.layers
# Delivers a list of RBA::LayerInfo objects representing the layers
# inside the source.
#
# One application is to read all layers from a source. In the following
# example, the "and" operation is used to perform a clip with the given
# rectangle. Note that this solution is not efficient - it's provided
# as an example only:
#
# @code
# output_cell("Clipped")
#
# clip_box = polygon_layer
# clip_box.insert(box(0.um, -4.um, 4.um, 0.um))
#
# layers.each { |l| (input(l) & clip_box).output(l) }
# @/code
def layers
@layout.layer_indices.collect { |li| @layout.get_info(li) }
end
end end
# The DRC engine # The DRC engine
@ -4283,6 +4319,16 @@ CODE
layout.input(*args) layout.input(*args)
end end
# %DRC%
# @name labels
# @brief Gets the labels (text) from an original layer
# @synopsis labels
# See \Source#labels for a description of that function.
def labels(*args)
layout.labels(*args)
end
# %DRC% # %DRC%
# @name output # @name output
# @brief Outputs a layer to the report database or output layout # @brief Outputs a layer to the report database or output layout
@ -4630,7 +4676,7 @@ CODE
end end
end end
def _input(layout, cell_index, layers, sel, box, clip, overlapping) def _input(layout, cell_index, layers, sel, box, clip, overlapping, labels_only)
if layers.empty? if layers.empty?
r = RBA::Region::new r = RBA::Region::new
@ -4641,6 +4687,9 @@ CODE
else else
iter = RBA::RecursiveShapeIterator::new(layout, layout.cell(cell_index), layers) iter = RBA::RecursiveShapeIterator::new(layout, layout.cell(cell_index), layers)
end end
if labels_only
iter.shape_flags = RBA::Shapes::STexts
end
sel.each do |s| sel.each do |s|
if s == "-" if s == "-"
@ -4658,6 +4707,13 @@ CODE
end end
end end
if labels_only
# for labels layers, the iterator is the data (no region)
r = iter
else
sf = layout.dbu / self.dbu sf = layout.dbu / self.dbu
if (sf - 1.0).abs > 1e-6 if (sf - 1.0).abs > 1e-6
r = RBA::Region::new(iter, RBA::ICplxTrans::new(sf.to_f)) r = RBA::Region::new(iter, RBA::ICplxTrans::new(sf.to_f))
@ -4672,6 +4728,8 @@ CODE
end end
end
r r
end end
@ -4690,7 +4748,12 @@ CODE
cat = @output_rdb.create_category(args[0].to_s) cat = @output_rdb.create_category(args[0].to_s)
args[1] && cat.description = args[1] args[1] && cat.description = args[1]
if data.is_a?(RBA::RecursiveShapeIterator)
@output_rdb.create_items(@output_rdb_cell_id, cat.rdb_id, data)
else
@output_rdb.create_items(@output_rdb_cell_id, cat.rdb_id, RBA::CplxTrans::new(self.dbu), data) @output_rdb.create_items(@output_rdb_cell_id, cat.rdb_id, RBA::CplxTrans::new(self.dbu), data)
end
else else

View File

@ -39,6 +39,7 @@ TEST(1)
"source(\"%s\", \"TOP\")\n" "source(\"%s\", \"TOP\")\n"
"target(\"%s\", \"TOP\")\n" "target(\"%s\", \"TOP\")\n"
"l1 = input(1, 0)\n" "l1 = input(1, 0)\n"
"l1t = labels(1, 0)\n"
"l2 = input(2, 0)\n" "l2 = input(2, 0)\n"
"l3 = input(3, 0)\n" "l3 = input(3, 0)\n"
"l1.output(1, 0)\n" "l1.output(1, 0)\n"
@ -46,6 +47,7 @@ TEST(1)
"l3.output(3, 0)\n" "l3.output(3, 0)\n"
"l1.space(0.5, projection).output(10, 0)\n" "l1.space(0.5, projection).output(10, 0)\n"
"(l2 & l3).output(11, 0)\n" "(l2 & l3).output(11, 0)\n"
"l1t.output(20, 0)\n"
, input, output) , input, output)
); );
drc.set_interpreter (lym::Macro::DSLInterpreter); drc.set_interpreter (lym::Macro::DSLInterpreter);

View File

@ -152,6 +152,15 @@ See <a href="/about/drc_ref_source.xml#input">Source#input</a> for a description
<ul> <ul>
<li><tt>is_tiled?</tt></li> <li><tt>is_tiled?</tt></li>
</ul> </ul>
<h2>"labels" - Gets the labels (text) from an original layer</h2>
<keyword name="labels"/>
<a name="labels"/><p>Usage:</p>
<ul>
<li><tt>labels</tt></li>
</ul>
<p>
See <a href="/about/drc_ref_source.xml#labels">Source#labels</a> for a description of that function.
</p>
<h2>"layers" - Gets the layers contained in the default source</h2> <h2>"layers" - Gets the layers contained in the default source</h2>
<keyword name="layers"/> <keyword name="layers"/>
<a name="layers"/><p>Usage:</p> <a name="layers"/><p>Usage:</p>

View File

@ -179,9 +179,7 @@ Here is a slow equivalent of the rotated method
<pre> <pre>
# Rotates by 45 degree # Rotates by 45 degree
t = <class_doc href="DCplxTrans">DCplxTrans</class_doc>(1.0, 45.0, false, <class_doc href="DVector">DVector</class_doc>::new) t = <class_doc href="DCplxTrans">DCplxTrans</class_doc>(1.0, 45.0, false, <class_doc href="DVector">DVector</class_doc>::new)
new_layer = layer.collect do |polygon| new_layer = layer.collect { |polygon| polygon.transformed(t) }
polygon.transformed(t)
end
</pre> </pre>
</p> </p>
<h2>"collect_to_edge_pairs" - Transforms a layer into edge pair objects</h2> <h2>"collect_to_edge_pairs" - Transforms a layer into edge pair objects</h2>
@ -239,7 +237,7 @@ The options available are:
<li><b>as_dots </b>: with this option, point-like edges will be produced instead of small boxes </li> <li><b>as_dots </b>: with this option, point-like edges will be produced instead of small boxes </li>
</ul> </ul>
</p><p> </p><p>
The following image shows the effect of this method The following images show the effect of this method:
</p><p> </p><p>
<table> <table>
<tr> <tr>
@ -1518,9 +1516,7 @@ apply to this method.
Here is a (slow) equivalent of the area selection method: Here is a (slow) equivalent of the area selection method:
</p><p> </p><p>
<pre> <pre>
new_layer = layer.select do |polygon| new_layer = layer.select { |polygon| polygon.area &gt;= 10.0 }
polygon.area &gt;= 10.0
end
</pre> </pre>
</p> </p>
<h2>"select_inside" - Selects shapes or regions of self which are inside the other region</h2> <h2>"select_inside" - Selects shapes or regions of self which are inside the other region</h2>

View File

@ -95,6 +95,33 @@ Some filter expressions are:
not have names)</li> not have names)</li>
</ul> </ul>
</p> </p>
<h2>"labels" - Gets the labels (texts) from an input layer</h2>
<keyword name="labels"/>
<a name="labels"/><p>Usage:</p>
<ul>
<li><tt>source.labels(layer)</tt></li>
<li><tt>source.labels(layer, datatype)</tt></li>
<li><tt>source.labels(layer_into)</tt></li>
<li><tt>source.labels(filter, ...)</tt></li>
</ul>
<p>
Creates a layer with the labels from the given layer of the source.
The layer can be specified by layer and optionally datatype, by a <class_doc href="LayerInfo">LayerInfo</class_doc>
object or by a sequence of filters.
Filters are expressions describing ranges
of layers and/or datatype numbers or layer names. Multiple filters
can be given and all layers matching at least one of these filter
expressions are joined to render the label collection. See "input" for
more details about the input layer specification.
</p><p>
Label layers currently can only be passed to an output layer.
Processing of labels is not supported. See "texts" for a way to filter
texts and use the text locations in geometrical operations.
</p><p>
<pre>
labels(1, 0).output(100, 0)
</pre>
</p>
<h2>"layers" - Gets the layers the source contains</h2> <h2>"layers" - Gets the layers the source contains</h2>
<keyword name="layers"/> <keyword name="layers"/>
<a name="layers"/><p>Usage:</p> <a name="layers"/><p>Usage:</p>

Binary file not shown.

View File

@ -801,7 +801,7 @@ class RDB_TestClass < TestBase
cat1 = rdb.create_category("l1") cat1 = rdb.create_category("l1")
cell1 = rdb.create_cell("c1") cell1 = rdb.create_cell("c1")
c0.shapes(l1).each do |s| c0.shapes(l1).each do |s|
rdb.create_item(cell1.rdb_id, cat1.rdb_id, s, RBA::CplxTrans::new(ly.dbu)) rdb.create_item(cell1.rdb_id, cat1.rdb_id, RBA::CplxTrans::new(ly.dbu), s)
end end
assert_equal(cat1.num_items, 1) assert_equal(cat1.num_items, 1)
cn = [] cn = []
@ -811,7 +811,7 @@ class RDB_TestClass < TestBase
rdb = RBA::ReportDatabase.new("neu") rdb = RBA::ReportDatabase.new("neu")
cat1 = rdb.create_category("l1") cat1 = rdb.create_category("l1")
cell1 = rdb.create_cell("c1") cell1 = rdb.create_cell("c1")
rdb.create_items(cell1.rdb_id, cat1.rdb_id, c0.shapes(l1), RBA::CplxTrans::new(ly.dbu)) rdb.create_items(cell1.rdb_id, cat1.rdb_id, RBA::CplxTrans::new(ly.dbu), c0.shapes(l1))
assert_equal(cat1.num_items, 1) assert_equal(cat1.num_items, 1)
cn = [] cn = []
rdb.each_cell { |c| cn << c.to_s_items } rdb.each_cell { |c| cn << c.to_s_items }