diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc
index 211c833fa..4c21ae9dd 100644
--- a/src/db/db/dbDeepShapeStore.cc
+++ b/src/db/db/dbDeepShapeStore.cc
@@ -911,7 +911,7 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
cm = m_delivery_mapping_cache.insert (std::make_pair (key, db::CellMapping ())).first;
// collects the cell mappings we skip because they are variants (variant building or box variants)
- std::map > > cm_skipped_variants;
+ std::map cm_skipped_variants;
if (into_layout == original_builder.source ().layout () && &into_layout->cell (into_cell) == original_builder.source ().top_cell ()) {
@@ -925,14 +925,14 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
HierarchyBuilder::cell_map_type::const_iterator mm = m;
++mm;
bool skip = original_builder.is_variant (m->second); // skip variant cells
- while (mm != original_builder.end_cell_map () && mm->first.first == m->first.first) {
+ while (mm != original_builder.end_cell_map () && mm->first.original_cell == m->first.original_cell) {
// we have cell (box) variants and cannot simply map
++mm;
skip = true;
}
if (! skip) {
- cm->second.map (m->second, m->first.first);
+ cm->second.map (m->second, m->first.original_cell);
} else {
for (HierarchyBuilder::cell_map_type::const_iterator n = m; n != mm; ++n) {
tl_assert (cm_skipped_variants.find (n->second) == cm_skipped_variants.end ());
@@ -968,17 +968,19 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
db::cell_index_type var_org = original_builder.original_target_for_variant (np->first);
- std::map > >::const_iterator icm = cm_skipped_variants.find (var_org);
+ std::map::const_iterator icm = cm_skipped_variants.find (var_org);
if (icm != cm_skipped_variants.end ()) {
// create the variant clone in the original layout too and delete this cell
- VariantsCollectorBase::copy_shapes (*into_layout, np->second, icm->second.first);
- cells_to_delete.insert (icm->second.first);
+ VariantsCollectorBase::copy_shapes (*into_layout, np->second, icm->second.original_cell);
+ cells_to_delete.insert (icm->second.original_cell);
// forget the original cell (now separated into variants) and map the variants back into the
// DSS layout
original_builder.unmap (icm->second);
- original_builder.map (std::make_pair (np->second, icm->second.second), np->first);
+ db::HierarchyBuilder::CellMapKey k = icm->second;
+ k.original_cell = np->second;
+ original_builder.map (k, np->first);
// forget the variant as now it's a real cell in the source layout
original_builder.unregister_variant (np->first);
diff --git a/src/db/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc
index 625183a11..7da387f93 100644
--- a/src/db/db/dbHierarchyBuilder.cc
+++ b/src/db/db/dbHierarchyBuilder.cc
@@ -62,6 +62,14 @@ compare_iterators_with_respect_to_target_hierarchy (const db::RecursiveShapeIter
return iter1.max_depth () < iter2.max_depth () ? -1 : 1;
}
+ // take potential selection of cells into account
+ if (iter1.disables () != iter2.disables ()) {
+ return iter1.disables () < iter2.disables () ? -1 : 1;
+ }
+ if (iter1.enables () != iter2.enables ()) {
+ return iter1.enables () < iter2.enables () ? -1 : 1;
+ }
+
// if a region is set, the hierarchical appearance is the same only if the layers and
// complex region are identical
if ((iter1.region () == db::Box::world ()) != (iter2.region () == db::Box::world ())) {
@@ -238,11 +246,11 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
return;
}
- std::pair > key (iter->top_cell ()->cell_index (), std::set ());
+ CellMapKey key (iter->top_cell ()->cell_index (), false, std::set ());
m_cm_entry = m_cell_map.find (key);
if (m_cm_entry == m_cell_map.end ()) {
- db::cell_index_type new_top_index = mp_target->add_cell (iter->layout ()->cell_name (key.first));
+ db::cell_index_type new_top_index = mp_target->add_cell (iter->layout ()->cell_name (key.original_cell));
m_cm_entry = m_cell_map.insert (std::make_pair (key, new_top_index)).first;
}
@@ -300,27 +308,47 @@ HierarchyBuilder::leave_cell (const RecursiveShapeIterator * /*iter*/, const db:
m_cell_stack.pop_back ();
}
+db::cell_index_type
+HierarchyBuilder::make_cell_variant (const HierarchyBuilder::CellMapKey &key, const std::string &cell_name)
+{
+ m_cm_entry = m_cell_map.find (key);
+ m_cm_new_entry = false;
+
+ db::cell_index_type new_cell;
+
+ if (m_cm_entry == m_cell_map.end ()) {
+
+ std::string cn = cell_name;
+ if (! key.clip_region.empty ()) {
+ cn += "$CLIP_VAR";
+ }
+ if (key.inactive) {
+ cn += "$DIS";
+ }
+ new_cell = mp_target->add_cell (cn.c_str ());
+ m_cm_entry = m_cell_map.insert (std::make_pair (key, new_cell)).first;
+ m_cm_new_entry = true;
+ m_cells_to_be_filled.insert (new_cell);
+
+ } else {
+ new_cell = m_cm_entry->second;
+ }
+
+ return new_cell;
+}
+
HierarchyBuilder::new_inst_mode
HierarchyBuilder::new_inst (const RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all)
{
if (all) {
- std::pair > key (inst.object ().cell_index (), std::set ());
-
- m_cm_entry = m_cell_map.find (key);
- m_cm_new_entry = false;
-
- if (m_cm_entry == m_cell_map.end ()) {
- db::cell_index_type new_cell = mp_target->add_cell (iter->layout ()->cell_name (inst.object ().cell_index ()));
- m_cm_entry = m_cell_map.insert (std::make_pair (key, new_cell)).first;
- m_cm_new_entry = true;
- m_cells_to_be_filled.insert (new_cell);
- }
+ CellMapKey key (inst.object ().cell_index (), iter->is_child_inactive (inst.object ().cell_index ()), std::set ());
+ db::cell_index_type new_cell = make_cell_variant (key, iter->layout ()->cell_name (inst.object ().cell_index ()));
// for new cells, create this instance
if (m_cell_stack.back ().first) {
db::CellInstArray new_inst (inst, &mp_target->array_repository ());
- new_inst.object () = db::CellInst (m_cm_entry->second);
+ new_inst.object () = db::CellInst (new_cell);
new_inst.transform_into (m_trans);
for (std::vector::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
(*c)->insert (new_inst);
@@ -353,24 +381,12 @@ HierarchyBuilder::new_inst_member (const RecursiveShapeIterator *iter, const db:
return false;
}
- std::pair > key (inst.object ().cell_index (), clip_variant.second);
- m_cm_entry = m_cell_map.find (key);
- m_cm_new_entry = false;
-
- if (m_cm_entry == m_cell_map.end ()) {
- std::string suffix;
- if (! key.second.empty ()) {
- suffix = "$CLIP_VAR";
- }
- db::cell_index_type new_cell = mp_target->add_cell ((std::string (iter->layout ()->cell_name (inst.object ().cell_index ())) + suffix).c_str ());
- m_cm_entry = m_cell_map.insert (std::make_pair (key, new_cell)).first;
- m_cm_new_entry = true;
- m_cells_to_be_filled.insert (new_cell);
- }
+ CellMapKey key (inst.object ().cell_index (), iter->is_child_inactive (inst.object ().cell_index ()), clip_variant.second);
+ db::cell_index_type new_cell = make_cell_variant (key, iter->layout ()->cell_name (inst.object ().cell_index ()));
// for a new cell, create this instance
if (m_cell_stack.back ().first) {
- db::CellInstArray new_inst (db::CellInst (m_cm_entry->second), trans);
+ db::CellInstArray new_inst (db::CellInst (new_cell), trans);
new_inst.transform_into (m_trans);
for (std::vector::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
(*c)->insert (new_inst);
diff --git a/src/db/db/dbHierarchyBuilder.h b/src/db/db/dbHierarchyBuilder.h
index b1d323dc7..374cdcbc3 100644
--- a/src/db/db/dbHierarchyBuilder.h
+++ b/src/db/db/dbHierarchyBuilder.h
@@ -208,8 +208,36 @@ class DB_PUBLIC HierarchyBuilder
: public db::RecursiveShapeReceiver
{
public:
+ struct CellMapKey
+ {
+ CellMapKey ()
+ : original_cell (0), inactive (false)
+ { }
- typedef std::map >, db::cell_index_type> cell_map_type;
+ CellMapKey (db::cell_index_type _original_cell, bool _inactive, const std::set &_clip_region)
+ : original_cell (_original_cell), inactive (_inactive), clip_region (_clip_region)
+ { }
+
+ bool operator== (const CellMapKey &other) const
+ {
+ return original_cell == other.original_cell && inactive == other.inactive && clip_region == other.clip_region;
+ }
+
+ bool operator< (const CellMapKey &other) const
+ {
+ if (original_cell != other.original_cell) { return original_cell < other.original_cell; }
+ if (inactive != other.inactive) { return inactive < other.inactive; }
+ if (clip_region != other.clip_region) { return clip_region < other.clip_region; }
+ return false;
+ }
+
+ db::cell_index_type original_cell;
+ bool inactive;
+ std::set clip_region;
+ };
+
+
+ typedef std::map cell_map_type;
typedef std::map > original_target_to_variants_map_type;
typedef std::map variant_to_original_target_map_type;
@@ -329,6 +357,8 @@ public:
db::cell_index_type original_target_for_variant (db::cell_index_type ci) const;
private:
+ db::cell_index_type make_cell_variant (const HierarchyBuilder::CellMapKey &key, const std::string &cell_name);
+
tl::weak_ptr mp_target;
HierarchyBuilderShapeReceiver *mp_pipe;
bool m_initial_pass;
diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc
index e3e571721..bbb6e763e 100644
--- a/src/db/db/dbRecursiveShapeIterator.cc
+++ b/src/db/db/dbRecursiveShapeIterator.cc
@@ -864,10 +864,9 @@ RecursiveShapeIterator::new_cell (RecursiveShapeReceiver *receiver) const
m_layer = m_layers.front ();
}
- if (! m_start.empty () && m_start.find (cell_index ()) != m_start.end ()) {
- set_inactive (false);
- } else if (! m_stop.empty () && m_stop.find (cell_index ()) != m_stop.end ()) {
- set_inactive (true);
+ bool new_cell_inactive = is_child_inactive (cell_index ());
+ if (is_inactive () != new_cell_inactive) {
+ set_inactive (new_cell_inactive);
}
new_layer ();
@@ -975,6 +974,18 @@ RecursiveShapeIterator::is_outside_complex_region (const db::Box &box) const
}
}
+bool
+RecursiveShapeIterator::is_child_inactive (db::cell_index_type new_child) const
+{
+ bool inactive = is_inactive ();
+ if (! m_start.empty () && m_start.find (new_child) != m_start.end ()) {
+ inactive = false;
+ } else if (! m_stop.empty () && m_stop.find (new_child) != m_stop.end ()) {
+ inactive = true;
+ }
+ return inactive;
+}
+
void
RecursiveShapeIterator::push (RecursiveShapeReceiver *receiver)
{
diff --git a/src/db/db/dbRecursiveShapeIterator.h b/src/db/db/dbRecursiveShapeIterator.h
index 40225b8d1..8dc398b95 100644
--- a/src/db/db/dbRecursiveShapeIterator.h
+++ b/src/db/db/dbRecursiveShapeIterator.h
@@ -704,6 +704,19 @@ public:
*/
void push (RecursiveShapeReceiver *receiver);
+ /**
+ * @brief Returns a value indicating whether the current cell is inactive (disabled)
+ */
+ bool is_inactive () const
+ {
+ return (reinterpret_cast (mp_cell) & size_t (1)) != 0;
+ }
+
+ /**
+ * @brief Returns a value indicating whether a new child cell of the current cell will be inactive
+ */
+ bool is_child_inactive (db::cell_index_type new_child) const;
+
private:
std::vector m_layers;
bool m_has_layers;
@@ -760,11 +773,6 @@ private:
bool is_outside_complex_region (const db::Box &box) const;
- bool is_inactive () const
- {
- return (reinterpret_cast (mp_cell) & size_t (1)) != 0;
- }
-
void set_inactive (bool a) const
{
size_t c = reinterpret_cast (mp_cell);
diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb
index 95c10fc5d..eed420fa2 100644
--- a/src/drc/drc/built-in-macros/_drc_engine.rb
+++ b/src/drc/drc/built-in-macros/_drc_engine.rb
@@ -1233,7 +1233,7 @@ module DRC
# @/code
#
# (Technically, the cheat code block is a Ruby Proc and cannot create variables
- # outside it's scope. Hence the results of this code block have to be passed
+ # outside its scope. Hence the results of this code block have to be passed
# through the "cheat" method).
#
# To apply cheats for device extraction, use the following scheme:
@@ -1809,7 +1809,7 @@ CODE
sel.each do |s|
if s == "-"
- iter.unselect_cells(cell.cell_index)
+ iter.unselect_cells([cell_index])
elsif s == "-*"
iter.unselect_all_cells
elsif s == "+*"
diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb
index 5caa60862..2d6d5a4a0 100644
--- a/src/drc/drc/built-in-macros/_drc_netter.rb
+++ b/src/drc/drc/built-in-macros/_drc_netter.rb
@@ -156,7 +156,7 @@ module DRC
# @li \global#capacitor_with_bulk - A capacitor with a separate bulk terminal @/li
# @/ul
#
- # Each device class (e.g. n-MOS/p-MOS or high Vt/low Vt) needs it's own instance
+ # Each device class (e.g. n-MOS/p-MOS or high Vt/low Vt) needs its own instance
# of device extractor. The device extractor beside the algorithm and specific
# extraction settings defines the name of the device to be built.
#
diff --git a/src/drc/drc/built-in-macros/_drc_source.rb b/src/drc/drc/built-in-macros/_drc_source.rb
index f047ff4a2..6cdfc6ab9 100644
--- a/src/drc/drc/built-in-macros/_drc_source.rb
+++ b/src/drc/drc/built-in-macros/_drc_source.rb
@@ -22,14 +22,27 @@ module DRC
@layout_var = layout_var
@path = path
@cell = cell
- @inside = nil
@box = nil
- @layers = nil
@sel = []
@clip = false
@overlapping = false
@tmp_layers = []
end
+
+ # Conceptual deep copy (not including the temp layers)
+ def dup
+ d = DRCSource::new(@engine, @layout, @layout_var, @cell, @path)
+ d._init_internal(@box ? @box.dup : nil, @sel.dup, @clip, @overlapping)
+ d
+ end
+
+ # internal copy initialization
+ def _init_internal(box, sel, clip, overlapping)
+ @box = box
+ @sel = sel
+ @clip = clip
+ @overlapping = overlapping
+ end
# %DRC%
# @name layout
@@ -139,19 +152,34 @@ module DRC
# code:
#
# @code
- # layout_with_selection = layout.select("-TOP", "+B")
- # l1 = layout_with_selection.input(1, 0)
+ # layout_with_selection = source.select("-TOP", "+B")
+ # l1 = source.input(1, 0)
# ...
# @/code
#
# Please note that the sample above will deliver the children of "B" because there is
- # nothing said about how to proceed with cells other than "TOP" or "B".
- # The following code will just select "B" without it's children, because in the
+ # nothing said about how to proceed with cells other than "TOP" or "B". Conceptually,
+ # the instantiation path of a cell will be matched against the different filters in the
+ # order they are given.
+ # A matching negative expression will disable the cell, a matching positive expression
+ # will enable the cell. Hence, every cell that has a "B" in the instantiation path
+ # is enabled.
+ #
+ # The following code will just select "B" without its children, because in the
# first "-*" selection, all cells including the children of "B" are disabled:
#
# @code
- # layout_with_selection = layout.select("-*", "+B")
- # l1 = layout_with_selection.input(1, 0)
+ # layout_with_selection = source.select("-*", "+B")
+ # l1 = source.input(1, 0)
+ # ...
+ # @/code
+ #
+ # The short form "-" will disable the top cell. This code is identical to the first example
+ # and will start with a disabled top cell regardless of its name:
+ #
+ # @code
+ # layout_with_selection = source.select("-", "+B")
+ # l1 = source.input(1, 0)
# ...
# @/code
diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc
index dad8bbc50..d87b3b746 100644
--- a/src/drc/unit_tests/drcSimpleTests.cc
+++ b/src/drc/unit_tests/drcSimpleTests.cc
@@ -714,3 +714,44 @@ TEST(15_issue548)
db::compare_layouts (_this, layout, au, db::NoNormalization);
}
+
+// Problems with Source#select
+TEST(17_issue570)
+{
+ std::string rs = tl::testsrc ();
+ rs += "/testdata/drc/drcSimpleTests_17.drc";
+
+ std::string input = tl::testsrc ();
+ input += "/testdata/drc/drcSimpleTests_17.gds";
+
+ std::string au = tl::testsrc ();
+ au += "/testdata/drc/drcSimpleTests_au17.gds";
+
+ std::string output = this->tmp_file ("tmp.gds");
+
+ {
+ // Set some variables
+ lym::Macro config;
+ config.set_text (tl::sprintf (
+ "$drc_test_source = '%s'\n"
+ "$drc_test_target = '%s'\n"
+ , input, output)
+ );
+ config.set_interpreter (lym::Macro::Ruby);
+ EXPECT_EQ (config.run (), 0);
+ }
+
+ lym::Macro drc;
+ drc.load_from (rs);
+ EXPECT_EQ (drc.run (), 0);
+
+ db::Layout layout;
+
+ {
+ tl::InputStream stream (output);
+ db::Reader reader (stream);
+ reader.read (layout);
+ }
+
+ db::compare_layouts (_this, layout, au, db::NoNormalization);
+}
diff --git a/src/lay/lay/doc/about/custom_queries.xml b/src/lay/lay/doc/about/custom_queries.xml
index 2f4f5acb0..02c70381b 100644
--- a/src/lay/lay/doc/about/custom_queries.xml
+++ b/src/lay/lay/doc/about/custom_queries.xml
@@ -104,7 +104,7 @@ cells T*
- A cell expression can already be used by it's own. The report of such a query will simply contain the cells
+ A cell expression can already be used by its own. The report of such a query will simply contain the cells
selected by that expression. If combined with an action, such expressions already provide useful manipulation
functionality.
@@ -243,7 +243,7 @@ cells TOP..A
is used in (including top cells and all child contexts). Used after a cell, it will return the cell
plus all child cells in each possible context. Used before a cell it will deliver all contexts that cell
is used in every top cells.
- The following query will deliver "TOP" plus all it's direct and indirect children:
+ The following query will deliver "TOP" plus all its direct and indirect children:
@@ -398,7 +398,7 @@ with shapes on layer 6 from instances of TOP.. do initial_cell.shapes(<10/0&g
- That expression reads all shapes of cell "TOP" and it's children, inserts them into a new layer 10, datatype 0 and
+ That expression reads all shapes of cell "TOP" and its children, inserts them into a new layer 10, datatype 0 and
transforms the shape after it has been inserted. This expression makes use of the variables "initial_cell" (a Cell object
representing the root cell of the cell query), "shape" (a pointer to the currently selected shape and "path_trans"
(a Trans object representing the transformation of the current shape into the root cell of the query).
diff --git a/src/lay/lay/doc/about/drc_ref_global.xml b/src/lay/lay/doc/about/drc_ref_global.xml
index 7e4be95ba..b807fd8c7 100644
--- a/src/lay/lay/doc/about/drc_ref_global.xml
+++ b/src/lay/lay/doc/about/drc_ref_global.xml
@@ -164,7 +164,7 @@ end
(Technically, the cheat code block is a Ruby Proc and cannot create variables
-outside it's scope. Hence the results of this code block have to be passed
+outside its scope. Hence the results of this code block have to be passed
through the "cheat" method).
To apply cheats for device extraction, use the following scheme:
diff --git a/src/lay/lay/doc/about/drc_ref_netter.xml b/src/lay/lay/doc/about/drc_ref_netter.xml
index 5b8f360a3..65f2fd892 100644
--- a/src/lay/lay/doc/about/drc_ref_netter.xml
+++ b/src/lay/lay/doc/about/drc_ref_netter.xml
@@ -296,7 +296,7 @@ Predefined device extractors are:
global#capacitor_with_bulk - A capacitor with a separate bulk terminal
-Each device class (e.g. n-MOS/p-MOS or high Vt/low Vt) needs it's own instance
+Each device class (e.g. n-MOS/p-MOS or high Vt/low Vt) needs its own instance
of device extractor. The device extractor beside the algorithm and specific
extraction settings defines the name of the device to be built.
diff --git a/src/lay/lay/doc/about/drc_ref_source.xml b/src/lay/lay/doc/about/drc_ref_source.xml
index a620c0b4b..197496d5d 100644
--- a/src/lay/lay/doc/about/drc_ref_source.xml
+++ b/src/lay/lay/doc/about/drc_ref_source.xml
@@ -233,19 +233,34 @@ To disable the TOP cell but enabled a hypothetical cell B below the top cell, us
code:
-layout_with_selection = layout.select("-TOP", "+B")
-l1 = layout_with_selection.input(1, 0)
+layout_with_selection = source.select("-TOP", "+B")
+l1 = source.input(1, 0)
...
Please note that the sample above will deliver the children of "B" because there is
-nothing said about how to proceed with cells other than "TOP" or "B".
-The following code will just select "B" without it's children, because in the
+nothing said about how to proceed with cells other than "TOP" or "B". Conceptually,
+the instantiation path of a cell will be matched against the different filters in the
+order they are given.
+A matching negative expression will disable the cell, a matching positive expression
+will enable the cell. Hence, every cell that has a "B" in the instantiation path
+is enabled.
+
+The following code will just select "B" without its children, because in the
first "-*" selection, all cells including the children of "B" are disabled:
-layout_with_selection = layout.select("-*", "+B")
-l1 = layout_with_selection.input(1, 0)
+layout_with_selection = source.select("-*", "+B")
+l1 = source.input(1, 0)
+...
+
+
+The short form "-" will disable the top cell. This code is identical to the first example
+and will start with a disabled top cell regardless of its name:
+
+
+layout_with_selection = source.select("-", "+B")
+l1 = source.input(1, 0)
...
diff --git a/src/lay/lay/doc/about/layer_mapping.xml b/src/lay/lay/doc/about/layer_mapping.xml
index b9209e016..81d6205db 100644
--- a/src/lay/lay/doc/about/layer_mapping.xml
+++ b/src/lay/lay/doc/about/layer_mapping.xml
@@ -130,7 +130,7 @@
If the match expression includes a numerical range or wildcards
for the layer or datatype number, by default all these layers
- will be combined into a single one, where it's layer or datatype number is derived
+ will be combined into a single one, where its layer or datatype number is derived
from the least permitted number.
diff --git a/src/lay/lay/doc/about/technology_manager.xml b/src/lay/lay/doc/about/technology_manager.xml
index 1cc3fa189..a9c508fa9 100644
--- a/src/lay/lay/doc/about/technology_manager.xml
+++ b/src/lay/lay/doc/about/technology_manager.xml
@@ -37,7 +37,7 @@
edited. Instead, a library installed in the system comes with a technology
association itself.
File format options: technology specific file reader or writer options can be
- given. When a layout is saved, it will use the writer options from it's technology.
+ given. When a layout is saved, it will use the writer options from its technology.
When loading a layout, the reader options from the active technology will be used.
diff --git a/src/lay/lay/doc/manual/copypaste_cell.xml b/src/lay/lay/doc/manual/copypaste_cell.xml
index 519e7ebf5..97d59e700 100644
--- a/src/lay/lay/doc/manual/copypaste_cell.xml
+++ b/src/lay/lay/doc/manual/copypaste_cell.xml
@@ -28,7 +28,7 @@
cells with the same name will be used as child cells.
- Deep copy: In deep copy mode, the cell plus it's child cells are copied. All cells will be carried
+ Deep copy: In deep copy mode, the cell plus its child cells are copied. All cells will be carried
along and when pasting the cell, copies of all children will be created as well.
diff --git a/src/lay/lay/doc/manual/create_instance.xml b/src/lay/lay/doc/manual/create_instance.xml
index 07f6c6897..11b6922ab 100644
--- a/src/lay/lay/doc/manual/create_instance.xml
+++ b/src/lay/lay/doc/manual/create_instance.xml
@@ -57,7 +57,7 @@
KLayout offers a unique feature for the PCell implementation: a PCell can employ "guiding shapes".
"Guiding shapes" are shapes that do not appear as layout themselves but are used by the PCell
- to derive it's geometry from. For example the "rounded path" PCell of the "Basic" library
+ to derive its geometry from. For example the "rounded path" PCell of the "Basic" library
uses a path as a guiding shape. This path is manipulated to obtain the final shape.
diff --git a/src/lay/lay/doc/manual/del_cell.xml b/src/lay/lay/doc/manual/del_cell.xml
index e03b36750..7662c96a7 100644
--- a/src/lay/lay/doc/manual/del_cell.xml
+++ b/src/lay/lay/doc/manual/del_cell.xml
@@ -13,13 +13,13 @@
- - Shallow delete: Just the cell (it's shapes and instances) are deleted, not
+
- Shallow delete: Just the cell (its shapes and instances) are deleted, not
any cells referenced by this cell. Since cells might no longer be referenced after
that, they may appear as new top cells in the layout.
- - Deep delete: The cell and all it's subcells are deleted, unless the subcells are
+
- Deep delete: The cell and all its subcells are deleted, unless the subcells are
referenced otherwise (by cells that are not deleted).
In this delete mode a complete hierarchy of cells can be removed without side effects.
- - Complete delete: The cell and all it's subcells are deleted, even if other cells
+
- Complete delete: The cell and all its subcells are deleted, even if other cells
would reference these subcells.
diff --git a/src/lay/lay/doc/manual/flatten.xml b/src/lay/lay/doc/manual/flatten.xml
index 9238089e8..d01579b59 100644
--- a/src/lay/lay/doc/manual/flatten.xml
+++ b/src/lay/lay/doc/manual/flatten.xml
@@ -8,7 +8,7 @@
- The "flatten cell" operation flattens a cell into all of it's parents.
+ The "flatten cell" operation flattens a cell into all of its parents.
This basically removes a cell by promoting her shapes and instances up in the hierarchy.
@@ -16,7 +16,7 @@
Cell flattening can be applied to single instances or cells as a whole.
When applied to an instance, the individual instance is resolved into shapes. The
instantiated cell will still exist afterwards. When applied to a cell, the cell
- will disappear and replaced by it's contents in all places it is used.
+ will disappear and replaced by its contents in all places it is used.
diff --git a/src/lay/lay/doc/manual/hier_ops.xml b/src/lay/lay/doc/manual/hier_ops.xml
index 7f010a337..326492d5f 100644
--- a/src/lay/lay/doc/manual/hier_ops.xml
+++ b/src/lay/lay/doc/manual/hier_ops.xml
@@ -23,7 +23,7 @@
are brought up to the current cell's level and removed from the original cell.
A non-destructive way of moving a shape up in the hierarchy is to copy and paste the shape. This does an
explicit flattening of the shapes selected when inserting them.
- Hint: the current implementation removes the selected object from it's original cell. Since it only creates
+ Hint: the current implementation removes the selected object from its original cell. Since it only creates
new copies for the selected instances, the object ist lost for all other instances of the cell. This may create undesired
side effects and it is likely that this behaviour will change in future implementations.
diff --git a/src/lay/lay/doc/manual/lvs_tweaks.xml b/src/lay/lay/doc/manual/lvs_tweaks.xml
index 2e631f677..12e4b0bf5 100644
--- a/src/lay/lay/doc/manual/lvs_tweaks.xml
+++ b/src/lay/lay/doc/manual/lvs_tweaks.xml
@@ -101,7 +101,7 @@
act as a wrapper to something else. In layouts, devices are often implemented as PCells and
appear as specific cells for no other reason than being implemented in a subcell. The same
might happen for schematic subcircuits which wrap a device. "Flattening" means that a circuit
- is removed and it's contents are integrated into the calling circuits.
+ is removed and its contents are integrated into the calling circuits.
diff --git a/src/lay/lay/doc/manual/main_window.xml b/src/lay/lay/doc/manual/main_window.xml
index d4a7f6ae6..c98c2ef45 100644
--- a/src/lay/lay/doc/manual/main_window.xml
+++ b/src/lay/lay/doc/manual/main_window.xml
@@ -10,7 +10,7 @@
The main window is divided into three parts: the left area is the hierarchy browser and navigator, the
center part of the canvas and the right part is the layer list with the layer toolbox.
The individual components can be rearranged, so the arrangement described is just the default
- arrangement. You can move a component to a new place by dragging it with it's title bar to
+ arrangement. You can move a component to a new place by dragging it with its title bar to
some other place or detach it from the main window to form a floating separate window.
diff --git a/src/lay/lay/doc/manual/move_sel.xml b/src/lay/lay/doc/manual/move_sel.xml
index 4799fd5d7..72403a30c 100644
--- a/src/lay/lay/doc/manual/move_sel.xml
+++ b/src/lay/lay/doc/manual/move_sel.xml
@@ -40,7 +40,7 @@
In the same way, "Move To" allows one to reposition the selection to a certain point. The point which
is positioned can be chosen relative to the bounding box of the selection. If first example,
the lower-left corner of the selection is picked as the reference point and a certain position
- is given in the dialog, the selection is moved such that the lower left position of it's
+ is given in the dialog, the selection is moved such that the lower left position of its
bounding box will match the given coordinate.
diff --git a/src/lay/lay/doc/manual/panels.xml b/src/lay/lay/doc/manual/panels.xml
index 1abaa5183..265baee06 100644
--- a/src/lay/lay/doc/manual/panels.xml
+++ b/src/lay/lay/doc/manual/panels.xml
@@ -30,7 +30,7 @@
Choose "Pull In Other Layout" to combine other layouts already loaded into the
current panel. Basically, KLayout allows viewsing a layout in multiple panels, either
- on it's own in different configurations or together with other layouts. "Pull In Other Layout"
+ on its own in different configurations or together with other layouts. "Pull In Other Layout"
allows configuration of a panel to show another layout which has been loaded into another panel.
In that sense it's the reverse of closing one layout from a panel showing multiple layouts.
diff --git a/src/lay/lay/doc/manual/ruler_properties.xml b/src/lay/lay/doc/manual/ruler_properties.xml
index bfcababf0..d889bd883 100644
--- a/src/lay/lay/doc/manual/ruler_properties.xml
+++ b/src/lay/lay/doc/manual/ruler_properties.xml
@@ -20,7 +20,7 @@
The Alignment of the labels can be specified too: whether the appear left or right-aligned
or centered.
- Style: the style determines how the ruler or it's components are drawn. This can be
+ Style: the style determines how the ruler or its components are drawn. This can be
"ruler-like" (with ticks), arrow style, a plain line or with cross markers at the end.
Outline: the outline determines how the two points forming the ruler are connected
@@ -31,7 +31,7 @@
Angle constraint: the orientation of the ruler can be restricted in several ways, i.e.
just being horizontal. By default, the ruler uses the global setting. It can however be configured
- to provide it's own constraint.
+ to provide its own constraint.
Object snapping: each ruler can be configure to snap to the closest object edge or vertex.
By default, the rulers use the global setting. It may be disabled however for each ruler.
diff --git a/src/lay/lay/doc/programming/application_api.xml b/src/lay/lay/doc/programming/application_api.xml
index 1fb7914fe..5baee3f8d 100644
--- a/src/lay/lay/doc/programming/application_api.xml
+++ b/src/lay/lay/doc/programming/application_api.xml
@@ -206,7 +206,7 @@ Application::instance.main_window.views
to a large degree, so different colors can be used for example. Markers are objects of class
Marker ().
- Local configuration: be default, the layout view pulls it's configuration from the global
+ Local configuration: be default, the layout view pulls its configuration from the global
configuration database. It is possible however to override certain configuration parameters for a
particular view. This allows for example to set the background color for a particular view without
affecting the other views.
@@ -703,7 +703,7 @@ layout_view.insert_layer(lp, props)
Width is a "weak" property. That means that for computing the effective width, child nodes
can override the settings inherited from the parent nodes. A width of 0 is considered "not set" and does not
override parent defined widths. Other properties like visibility are "strong", i.e.
- the parent can override the properties set for it's children. Another form of combination is "additive" where
+ the parent can override the properties set for its children. Another form of combination is "additive" where
the effective property value is the "sum" (or in general combination) of all local properties from parent
to child.
diff --git a/src/lay/lay/doc/programming/database_api.xml b/src/lay/lay/doc/programming/database_api.xml
index 3607af938..152ac2bff 100644
--- a/src/lay/lay/doc/programming/database_api.xml
+++ b/src/lay/lay/doc/programming/database_api.xml
@@ -161,7 +161,7 @@ layout.write("my_layout.gds")
- A layout can provide and import PCells. PCells are cells that provide it's geometry through program code
+ A layout can provide and import PCells. PCells are cells that provide its geometry through program code
(for example written in Ruby) and provide parameters which can be adjusted to change the appearance of the
cell. For each PCell a "declaration" must be provided which basically contains the code for the
PCell and some information about the parameters provided by the PCell. PCells are stored in the layout
@@ -813,7 +813,7 @@ end
- Despite it's name, a object holds a cell reference which is
+ Despite its name, a object holds a cell reference which is
not only an array, but also a single instances. The object represents a raw instance, in contrast to the
Instance object which is basically a pointer to an instance inside the database. CellInstArray objects as raw instances can be created,
copied, modified and stored in the usual containers, but once they are stored inside the Cell object, they can
@@ -1060,7 +1060,7 @@ end
The object provides a unified view to a geometrical primitive inside
a Shapes container. It also plays an important role for addressing geometrical primitives
inside a Shapes container. A Shape object has general methods and specific methods that apply
- depending on it's identity.
+ depending on its identity.
General methods
diff --git a/src/lay/lay/doc/programming/events.xml b/src/lay/lay/doc/programming/events.xml
index ee9b4e657..827102a7c 100644
--- a/src/lay/lay/doc/programming/events.xml
+++ b/src/lay/lay/doc/programming/events.xml
@@ -108,7 +108,7 @@ end
Events are the callback variant which is the easiest one to use. Using an event it is possible
to directly attach a block of code to a callback. An event has a specific signature, i.e.
- the parameters it provides. The block can obtain this parameters by listing them in it's argument list.
+ the parameters it provides. The block can obtain this parameters by listing them in its argument list.
diff --git a/src/lay/lay/doc/programming/geometry_api.xml b/src/lay/lay/doc/programming/geometry_api.xml
index e0628293c..cff528b57 100644
--- a/src/lay/lay/doc/programming/geometry_api.xml
+++ b/src/lay/lay/doc/programming/geometry_api.xml
@@ -36,7 +36,7 @@
The object represents an integer coordinate in the 2-dimensional layout space,
expressed in database units.
That object provides the x and y coordinates through the and attributes. Points can be added,
- subtracted, the euclidian distance and it's square can be computed using the and
+ subtracted, the euclidian distance and its square can be computed using the and
methods. The * operator used with a factor as the second operand will scale both the x and y coordinates.
@@ -113,7 +113,7 @@
Box + Point: computes the box that encloses the box and the point given
as the second operand. It basically enlarges the first box so it includes the second point as well.
- contains?(Point): returns true, if the point is inside the box or on it's edges.
+ contains?(Point): returns true, if the point is inside the box or on its edges.
enlarge(Point): will enlarge the box by the x and y coordinates of the Point. Basically the x value
of the point is subtracted from the left side and added to the right. The same way, the y coordinate is added
@@ -272,7 +272,7 @@ box = RBA::Box::new(dbox)
A object represents a line with a certain width. The figure above depicts the basic properties
- of a path. The basic geometry of a path is defined by it's spine - a sequence of points that the path follows.
+ of a path. The basic geometry of a path is defined by its spine - a sequence of points that the path follows.
By default, a path has rectangular end caps with variable length. The end caps can be round, in which case the extension
should be half the path width to avoid paths which are not compatible with the GDS2 format. Round-ended paths return
true on . An example for such a path is depicted in the following figure:
@@ -641,7 +641,7 @@ ly.top_cell.shapes(ly.layer(100, 0)).insert(r11 & r21)
edge pair collections, not regions. Each edge pair marks a
violation of the given check.
- replaces each polygon with it's bounding box.
+ replaces each polygon with its bounding box.
performs an on-grid check returning edge pairs for off-grid markers.
identifies holes and delivers a new region with the holes as filled polygons.
identifies holes and delivers a new region without the holes.
diff --git a/src/lay/lay/doc/programming/qt_binding.xml b/src/lay/lay/doc/programming/qt_binding.xml
index ae227cfa3..7d5c22b3a 100644
--- a/src/lay/lay/doc/programming/qt_binding.xml
+++ b/src/lay/lay/doc/programming/qt_binding.xml
@@ -165,7 +165,7 @@ end
- When a Qt object is created in Ruby space with a parent, it's
+ When a Qt object is created in Ruby space with a parent, its
ownership is passed to the parent. It is safe however to keep a reference to that object, because
KLayout's Ruby binding employs a special Ruby class internally (a proxy) which keeps track of the lifetime
of the Qt object. If the parent is destroyed, the Qt object is destroyed as well. The internal Qt object will
diff --git a/src/lay/lay/doc/programming/ruby_binding.xml b/src/lay/lay/doc/programming/ruby_binding.xml
index 07cc293e2..9236c4a32 100644
--- a/src/lay/lay/doc/programming/ruby_binding.xml
+++ b/src/lay/lay/doc/programming/ruby_binding.xml
@@ -119,7 +119,7 @@ cell.shapes(layer).insert(box)
An exception to the lifetime control rule given above are Qt objects: a common pattern is to create Qt objects
and add them to a container (i.e. widgets to a dialog). This implies a lifetime control transfer from
Ruby to C++. RBA handles that case by explicitly transferring control when a QObject or one of the
- derived objects is created with a parent reference in Ruby code. Qt implements it's own mechanism of controlling
+ derived objects is created with a parent reference in Ruby code. Qt implements its own mechanism of controlling
the lifetime which includes monitoring of the lifetime of child objects. This feature makes transferring the
control feasible for these kind of objects. For some Qt methods which are know to transfer the ownership
of an object, the ownership is transferred explicitly.
diff --git a/src/lay/lay/doc/programming/ruby_pcells.xml b/src/lay/lay/doc/programming/ruby_pcells.xml
index caabcf7ac..d068d3ef5 100644
--- a/src/lay/lay/doc/programming/ruby_pcells.xml
+++ b/src/lay/lay/doc/programming/ruby_pcells.xml
@@ -310,7 +310,7 @@ end
is used for the cell tree and cell box labels. To avoid confusion, it should start with the name of the
PCell. The bracket notation is not mandatory, but it's always a good idea to follow some common style.
The information delivered by this method should be short but contain enough information so that a
- PCell variant can be distinguished from it's sibling.
+ PCell variant can be distinguished from its sibling.
diff --git a/testdata/drc/drcSimpleTests_17.drc b/testdata/drc/drcSimpleTests_17.drc
new file mode 100644
index 000000000..8cdbc5992
--- /dev/null
+++ b/testdata/drc/drcSimpleTests_17.drc
@@ -0,0 +1,42 @@
+
+source($drc_test_source)
+in_cell = source.select("-", "+S*")
+not_in_cell = source.select("-SPECIAL")
+in_cell_local = source.select("-*", "+SPECIAL")
+not_in_cell_local = source.select("+*", "-SPECIAL")
+
+target($drc_test_target)
+
+deep
+
+input(2,0).output(2, 0)
+input(3,0).output(3, 0)
+
+flat
+
+in_cell.input(2, 0).output(102, 0)
+in_cell.input(3, 0).output(103, 0)
+
+not_in_cell.input(2, 0).output(202, 0)
+not_in_cell.input(3, 0).output(203, 0)
+
+in_cell_local.input(2, 0).output(302, 0)
+in_cell_local.input(3, 0).output(303, 0)
+
+not_in_cell_local.input(2, 0).output(402, 0)
+not_in_cell_local.input(3, 0).output(403, 0)
+
+deep
+
+in_cell.input(2, 0).output(502, 0)
+in_cell.input(3, 0).output(503, 0)
+
+not_in_cell.input(2, 0).output(602, 0)
+not_in_cell.input(3, 0).output(603, 0)
+
+in_cell_local.input(2, 0).output(702, 0)
+in_cell_local.input(3, 0).output(703, 0)
+
+not_in_cell_local.input(2, 0).output(802, 0)
+not_in_cell_local.input(3, 0).output(803, 0)
+
diff --git a/testdata/drc/drcSimpleTests_17.gds b/testdata/drc/drcSimpleTests_17.gds
new file mode 100644
index 000000000..0718d5171
Binary files /dev/null and b/testdata/drc/drcSimpleTests_17.gds differ
diff --git a/testdata/drc/drcSimpleTests_au17.gds b/testdata/drc/drcSimpleTests_au17.gds
new file mode 100644
index 000000000..ceeb45db2
Binary files /dev/null and b/testdata/drc/drcSimpleTests_au17.gds differ