diff --git a/Changelog b/Changelog index 138367007..9a4524b08 100644 --- a/Changelog +++ b/Changelog @@ -3,21 +3,21 @@ * YET TO BE RELEASED * Enhancement: Standalone Python modules provided For details see: - https://github.com/klayoutmatthias/klayout/wiki/klayout---Standalone-KLayout-Python-Module + %GITHUB%/wiki/klayout---Standalone-KLayout-Python-Module 0.25.5 (2018-09-30): -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/162 +* Bugfix: %GITHUB%/issues/162 GDS2 LIBNAME was not maintained on "File/Save". -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/166 +* Bugfix: %GITHUB%/issues/166 Internal error when writing GDS files (breaking of polygons) -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/172 +* Bugfix: %GITHUB%/issues/172 DEF reader did not pull vias from LEF -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/174 +* Bugfix: %GITHUB%/issues/174 Performance issue with many layers with width >1 -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/176 +* Bugfix: %GITHUB%/issues/176 Painting issue with texts -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/185 +* Bugfix: %GITHUB%/issues/185 Hash values available as __hash__ standard method now for Python * Bugfix: some potential memory corruption issues fixed @@ -27,36 +27,36 @@ These fixes are included in this release. 0.25.4 (2018-08-25): -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/121 +* Bugfix: %GITHUB%/issues/121 Issue with multiple reads of GDS2 layouts including PCells -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/134 +* Bugfix: %GITHUB%/issues/134 Error in cell.fill_region caused by big polygon with spikes -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/139 +* Bugfix: %GITHUB%/issues/139 Libraries have not been reassigned when loading a GDS file from command line (does not happen on File/Open) -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/141 +* Bugfix: %GITHUB%/issues/141 Issue with RBA::QHostAddress (ambiguous overload) on Qt5 -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/142 +* Bugfix: %GITHUB%/issues/142 Issue with RBA::RecursiveShapeIterator#region= -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/144 +* Bugfix: %GITHUB%/issues/144 The Salt package descriptions are not shown with Motif style -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/148 +* Bugfix: %GITHUB%/issues/148 Wrong font is used -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/152 +* Bugfix: %GITHUB%/issues/152 Shapes#size reported a wrong shape count in viewer mode -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/153 +* Bugfix: %GITHUB%/issues/153 Application crash when editing guiding shape properties -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/155 +* Bugfix: %GITHUB%/issues/155 Program freezes after replacing nothing by something in Macro editor -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/157 +* Bugfix: %GITHUB%/issues/157 "Replace cell with ..." rejected cell names with a library prefix -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/158 +* Bugfix: %GITHUB%/issues/158 Repaint issue on cell context -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/159 +* Bugfix: %GITHUB%/issues/159 Tech specific macros and DRC scripts were not shown in tech manager * Bugfix: 8 bit indexed GIF images can be used for package icons now @@ -118,41 +118,41 @@ * Bugfix: XOR progress is more realistic The progress is updated after the layer has been computed, not before. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/117 +* Bugfix: %GITHUB%/issues/117 DTrans#itype was broken. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/116 +* Bugfix: %GITHUB%/issues/116 Fixed a polygon decomposition bug when writing GDS files with big polygons with many holes. As a side effect, the polygons with many holes computed by a NOT operation for example are less complex and spikes in the cutlines are avoided. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/115 +* Bugfix: %GITHUB%/issues/115 Reader options were not persisted. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/114 +* Bugfix: %GITHUB%/issues/114 Custom line styles not loaded from tech's layer properties file. -* Enhancement: https://github.com/klayoutmatthias/klayout/issues/113 +* Enhancement: %GITHUB%/issues/113 The XOR tool has an option now to heal result shapes which cross tile boundaries. The result shape count of tiled and non-tiled mode should basically be the same then. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/112 +* Bugfix: %GITHUB%/issues/112 Salt package repository relative paths have not been working. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/109 +* Bugfix: %GITHUB%/issues/109 Issues with Python 3 and shape properties - property -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/108 +* Bugfix: %GITHUB%/issues/108 Bugfix on Box#enlarge and Box#moved for empty boxes. keys generated with Python 3 could not be written to GDS2. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/107 +* Bugfix: %GITHUB%/issues/107 Undo not working with shapes. -* Enhancement: https://github.com/klayoutmatthias/klayout/issues/106 +* Enhancement: %GITHUB%/issues/106 Search & replace help page enhancements. 0.25.2 (2018-03-20): -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/90 +* Bugfix: %GITHUB%/issues/90 DRC: "extended" was not working as expected with "joined = true" -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/89 +* Bugfix: %GITHUB%/issues/89 Display issue on MacOS fixed -* Enhancement: https://github.com/klayoutmatthias/klayout/issues/85 +* Enhancement: %GITHUB%/issues/85 IDE debugger: files can be excluded from showing exceptions when they are thrown. To exclude a file press the new "Ignore" button when the debugger tells you an exception has been generated. @@ -160,7 +160,7 @@ in the IDE settings ("Debugging" tab) The macro IDE settings can now be edited in the File/Setup dialog. -* Bugfix: https://github.com/klayoutmatthias/klayout/issues/94 +* Bugfix: %GITHUB%/issues/94 Retina displays are support to some extend on MacOS. An open topic is the quality of the icons. * Enhancement: build system for MacOS @@ -174,40 +174,40 @@ - A potential crash ob removing packages was fixed * Enhancement: 64 bit coordinate support enabled on Windows builds * Further bugfixes: See links - - https://github.com/klayoutmatthias/klayout/issues/21 (Autorun(-early) doesn't seem to run when lym files are inside a package) - - https://github.com/klayoutmatthias/klayout/issues/24 (Text insert dialog bug - Ok button isn't working) - - https://github.com/klayoutmatthias/klayout/issues/26 (Exceptions are reported every time they propagate up in the call chain in the ruby debugger) - - https://github.com/klayoutmatthias/klayout/issues/28 (CIF format detection failed) - - https://github.com/klayoutmatthias/klayout/issues/30 (Writer options dialog non-functional on a fresh configuration) - - https://github.com/klayoutmatthias/klayout/issues/32 (Rounding issue with instance properties) - - https://github.com/klayoutmatthias/klayout/issues/33 (Plugin factory not working when using with Python) - - https://github.com/klayoutmatthias/klayout/issues/36 (Hardening against destruction of object inside event handler) - - https://github.com/klayoutmatthias/klayout/issues/39 (Action cannot be reassigned) - - https://github.com/klayoutmatthias/klayout/issues/40 (Crash in Python binding) - - https://github.com/klayoutmatthias/klayout/issues/41 (Polygon#touches? issue) - - https://github.com/klayoutmatthias/klayout/issues/42 (Headless mode support with Qt5/-zz) - - https://github.com/klayoutmatthias/klayout/issues/43 (Crash when using Qt specific command line options) - - https://github.com/klayoutmatthias/klayout/issues/44 (Transformation constructor with x,y not working) - - https://github.com/klayoutmatthias/klayout/issues/45 (Partial selection does not capture instance) - - https://github.com/klayoutmatthias/klayout/issues/48 (Cancel does not reset current tool) - - https://github.com/klayoutmatthias/klayout/issues/51 (Segmentation fault on return to main window and other opportunities) - - https://github.com/klayoutmatthias/klayout/issues/53 (Unreadable 'about' text) - - https://github.com/klayoutmatthias/klayout/issues/62 (QXmlSimpleReader#parse cannot be called) - - https://github.com/klayoutmatthias/klayout/issues/63 (Wrong output on DRC non_interacting with empty second input) - - https://github.com/klayoutmatthias/klayout/issues/64 (Crash on exit) - - https://github.com/klayoutmatthias/klayout/issues/68 (OASIS reader issue with degenerated shapes) - - https://github.com/klayoutmatthias/klayout/issues/69 (DRC: 'inside' does not merge shapes of second input) - - https://github.com/klayoutmatthias/klayout/issues/71 (Target cell argument is required) - - https://github.com/klayoutmatthias/klayout/issues/72 (Edges/Region NOT issue) - - https://github.com/klayoutmatthias/klayout/issues/73 (Allow 'change layers' on PCells which support a single layer parameter) - - https://github.com/klayoutmatthias/klayout/issues/74 (Small-corner boolean issue) - - https://github.com/klayoutmatthias/klayout/issues/75 (Python PCell issue when parameters are called 'layer') - - https://github.com/klayoutmatthias/klayout/issues/79 (Replace function enabled also for read-only macros) + - %GITHUB%/issues/21 (Autorun(-early) doesn't seem to run when lym files are inside a package) + - %GITHUB%/issues/24 (Text insert dialog bug - Ok button isn't working) + - %GITHUB%/issues/26 (Exceptions are reported every time they propagate up in the call chain in the ruby debugger) + - %GITHUB%/issues/28 (CIF format detection failed) + - %GITHUB%/issues/30 (Writer options dialog non-functional on a fresh configuration) + - %GITHUB%/issues/32 (Rounding issue with instance properties) + - %GITHUB%/issues/33 (Plugin factory not working when using with Python) + - %GITHUB%/issues/36 (Hardening against destruction of object inside event handler) + - %GITHUB%/issues/39 (Action cannot be reassigned) + - %GITHUB%/issues/40 (Crash in Python binding) + - %GITHUB%/issues/41 (Polygon#touches? issue) + - %GITHUB%/issues/42 (Headless mode support with Qt5/-zz) + - %GITHUB%/issues/43 (Crash when using Qt specific command line options) + - %GITHUB%/issues/44 (Transformation constructor with x,y not working) + - %GITHUB%/issues/45 (Partial selection does not capture instance) + - %GITHUB%/issues/48 (Cancel does not reset current tool) + - %GITHUB%/issues/51 (Segmentation fault on return to main window and other opportunities) + - %GITHUB%/issues/53 (Unreadable 'about' text) + - %GITHUB%/issues/62 (QXmlSimpleReader#parse cannot be called) + - %GITHUB%/issues/63 (Wrong output on DRC non_interacting with empty second input) + - %GITHUB%/issues/64 (Crash on exit) + - %GITHUB%/issues/68 (OASIS reader issue with degenerated shapes) + - %GITHUB%/issues/69 (DRC: 'inside' does not merge shapes of second input) + - %GITHUB%/issues/71 (Target cell argument is required) + - %GITHUB%/issues/72 (Edges/Region NOT issue) + - %GITHUB%/issues/73 (Allow 'change layers' on PCells which support a single layer parameter) + - %GITHUB%/issues/74 (Small-corner boolean issue) + - %GITHUB%/issues/75 (Python PCell issue when parameters are called 'layer') + - %GITHUB%/issues/79 (Replace function enabled also for read-only macros) * Further enhancements: see links - - https://github.com/klayoutmatthias/klayout/issues/29 (Permissive mode for OASIS writer on odd-width paths) - - https://github.com/klayoutmatthias/klayout/issues/59 (Async download of package index and details) - - https://github.com/klayoutmatthias/klayout/issues/66 (Authentication dialog indicates retry) - - https://github.com/klayoutmatthias/klayout/issues/77 (Layout#copy_tree now works in non-editable mode too) + - %GITHUB%/issues/29 (Permissive mode for OASIS writer on odd-width paths) + - %GITHUB%/issues/59 (Async download of package index and details) + - %GITHUB%/issues/66 (Authentication dialog indicates retry) + - %GITHUB%/issues/77 (Layout#copy_tree now works in non-editable mode too) 0.25 (2017-11-04): * Enhancement: Menu customization @@ -269,7 +269,7 @@ Packages can be published on GitHub or any server supporting WebDAV. After registering a package, users can install or update packages with a few clicks. - For more information see https://github.com/klayoutmatthias/klayout/wiki + For more information see %GITHUB%/wiki or "About Packages" in the "Various Topics" area of the main documentation. The package manager is found in the "Tools" menu under "Manage Packages". diff --git a/scripts/klayout-inst.nsis b/scripts/klayout-inst.nsis index 7d6244294..91d36a508 100644 --- a/scripts/klayout-inst.nsis +++ b/scripts/klayout-inst.nsis @@ -68,6 +68,8 @@ section file *.dll file strm*.exe file .*-paths.txt + file /r db_plugins + file /r lay_plugins file /r audio file /r generic file /r iconengines diff --git a/src/db/db/db.pro b/src/db/db/db.pro index f74dd864e..fd68bd081 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -309,7 +309,8 @@ HEADERS = \ dbDeepEdgePairs.h \ dbRegionUtils.h \ dbEdgesUtils.h \ - dbRegionProcessors.h + dbRegionProcessors.h \ + gsiDeclDbHelpers.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbCellMapping.cc b/src/db/db/dbCellMapping.cc index 9554e79ba..7d29d5d13 100644 --- a/src/db/db/dbCellMapping.cc +++ b/src/db/db/dbCellMapping.cc @@ -72,13 +72,25 @@ struct SortedCellIndexIterator SortedCellIndexIterator &operator++() { ++m_n; - return *this; + return *this; } SortedCellIndexIterator &operator+=(size_t n) { m_n += n; - return *this; + return *this; + } + + SortedCellIndexIterator &operator--() + { + --m_n; + return *this; + } + + SortedCellIndexIterator &operator-=(size_t n) + { + m_n -= n; + return *this; } bool operator==(const SortedCellIndexIterator &d) const diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index 74e5fbf7b..78a45c63f 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -1778,9 +1778,32 @@ public: } } + LayoutLocker (const LayoutLocker &other) + : mp_layout (other.mp_layout) + { + if (mp_layout) { + mp_layout->start_changes (); + } + } + + LayoutLocker &operator= (const LayoutLocker &other) + { + if (this == &other) { + return *this; + } + + if (mp_layout) { + mp_layout->end_changes (); + } + mp_layout = other.mp_layout; + if (mp_layout) { + mp_layout->start_changes (); + } + + return *this; + } + private: - LayoutLocker (const LayoutLocker &); - LayoutLocker &operator= (const LayoutLocker &); db::Layout *mp_layout; }; diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index 5025c7a21..92e13c342 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -23,6 +23,8 @@ #include "gsiDecl.h" + +#include "gsiDeclDbHelpers.h" #include "dbLayout.h" #include "dbBoxConvert.h" #include "dbRegion.h" @@ -711,70 +713,70 @@ static void dump_mem_statistics (const db::Cell *cell, bool detailed) ms.print (); } -static db::Shapes::shape_iterator begin_shapes (const db::Cell *s, unsigned int layer_index, unsigned int flags) +static gsi::layout_locking_iterator1 begin_shapes (const db::Cell *s, unsigned int layer_index, unsigned int flags) { - return s->begin (layer_index, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin (layer_index, flags)); } -static db::Shapes::shape_iterator begin_shapes_all (const db::Cell *s, unsigned int layer_index) +static gsi::layout_locking_iterator1 begin_shapes_all (const db::Cell *s, unsigned int layer_index) { - return s->begin (layer_index, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin (layer_index, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_touching_shapes (const db::Cell *s, unsigned int layer_index, const db::Box &box, unsigned int flags) +static gsi::layout_locking_iterator1 begin_touching_shapes (const db::Cell *s, unsigned int layer_index, const db::Box &box, unsigned int flags) { - return s->begin_touching (layer_index, box, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (layer_index, box, flags)); } -static db::Shapes::shape_iterator begin_touching_shapes_all (const db::Cell *s, unsigned int layer_index, const db::Box &box) +static gsi::layout_locking_iterator1 begin_touching_shapes_all (const db::Cell *s, unsigned int layer_index, const db::Box &box) { - return s->begin_touching (layer_index, box, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (layer_index, box, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_overlapping_shapes (const db::Cell *s, unsigned int layer_index, const db::Box &box, unsigned int flags) +static gsi::layout_locking_iterator1 begin_overlapping_shapes (const db::Cell *s, unsigned int layer_index, const db::Box &box, unsigned int flags) { - return s->begin_overlapping (layer_index, box, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (layer_index, box, flags)); } -static db::Shapes::shape_iterator begin_overlapping_shapes_all (const db::Cell *s, unsigned int layer_index, const db::Box &box) +static gsi::layout_locking_iterator1 begin_overlapping_shapes_all (const db::Cell *s, unsigned int layer_index, const db::Box &box) { - return s->begin_overlapping (layer_index, box, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (layer_index, box, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_touching_shapes_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box, unsigned int flags) +static gsi::layout_locking_iterator1 begin_touching_shapes_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box, unsigned int flags) { const db::Layout *layout = s->layout (); if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer search box"))); } - return s->begin_touching (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, flags)); } -static db::Shapes::shape_iterator begin_touching_shapes_all_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box) +static gsi::layout_locking_iterator1 begin_touching_shapes_all_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box) { const db::Layout *layout = s->layout (); if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer search box"))); } - return s->begin_touching (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_overlapping_shapes_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box, unsigned int flags) +static gsi::layout_locking_iterator1 begin_overlapping_shapes_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box, unsigned int flags) { const db::Layout *layout = s->layout (); if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer search box"))); } - return s->begin_overlapping (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, flags)); } -static db::Shapes::shape_iterator begin_overlapping_shapes_all_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box) +static gsi::layout_locking_iterator1 begin_overlapping_shapes_all_um (const db::Cell *s, unsigned int layer_index, const db::DBox &box) { const db::Layout *layout = s->layout (); if (! layout) { throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer search box"))); } - return s->begin_overlapping (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (layer_index, db::CplxTrans (layout->dbu ()).inverted () * box, db::ShapeIterator::All)); } static db::Instance insert_inst_with_props (db::Cell *c, const db::Cell::cell_inst_array_type &inst, db::properties_id_type id) @@ -1676,18 +1678,12 @@ static db::DBox cell_dbbox_per_layer (const db::Cell *cell, unsigned int layer_i return cell->bbox (layer_index) * layout->dbu (); } -static db::Cell::overlapping_iterator cell_begin_overlapping_inst_um (const db::Cell *cell, const db::DBox &db) +gsi::layout_locking_iterator1 begin_overlapping_inst (const db::Cell *cell, const db::Cell::box_type &b) { - const db::Layout *layout = cell->layout (); - if (! layout) { - throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer-unit search boxes"))); - } - - db::CplxTrans dbu_trans (layout->dbu ()); - return cell->begin_overlapping (dbu_trans.inverted () * db); + return gsi::layout_locking_iterator1 (cell->layout (), cell->begin_overlapping (b)); } -static db::Cell::touching_iterator cell_begin_touching_inst_um (const db::Cell *cell, const db::DBox &db) +gsi::layout_locking_iterator1 begin_overlapping_inst_um (const db::Cell *cell, const db::DBox &dbox) { const db::Layout *layout = cell->layout (); if (! layout) { @@ -1695,7 +1691,43 @@ static db::Cell::touching_iterator cell_begin_touching_inst_um (const db::Cell * } db::CplxTrans dbu_trans (layout->dbu ()); - return cell->begin_touching (dbu_trans.inverted () * db); + return gsi::layout_locking_iterator1 (cell->layout (), cell->begin_overlapping (dbu_trans.inverted () * dbox)); +} + +gsi::layout_locking_iterator1 begin_touching_inst (const db::Cell *cell, const db::Cell::box_type &b) +{ + return gsi::layout_locking_iterator1 (cell->layout (), cell->begin_touching (b)); +} + +gsi::layout_locking_iterator1 begin_touching_inst_um (const db::Cell *cell, const db::DBox &dbox) +{ + const db::Layout *layout = cell->layout (); + if (! layout) { + throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer-unit search boxes"))); + } + + db::CplxTrans dbu_trans (layout->dbu ()); + return gsi::layout_locking_iterator1 (cell->layout (), cell->begin_touching (dbu_trans.inverted () * dbox)); +} + +gsi::layout_locking_iterator1 begin_child_cells (const db::Cell *cell) +{ + return gsi::layout_locking_iterator1 (cell->layout (), cell->begin_child_cells ()); +} + +gsi::layout_locking_iterator1 begin_parent_insts (const db::Cell *cell) +{ + return gsi::layout_locking_iterator1 (cell->layout (), cell->begin_parent_insts ()); +} + +gsi::layout_locking_iterator2 begin_parent_cells (const db::Cell *cell) +{ + return gsi::layout_locking_iterator2 (cell->layout (), cell->begin_parent_cells (), cell->end_parent_cells ()); +} + +static layout_locking_iterator1 begin_inst (db::Cell *cell) +{ + return layout_locking_iterator1 (cell->layout (), cell->begin ()); } Class decl_Cell ("db", "Cell", @@ -2566,7 +2598,7 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been introduced in version 0.25." ) + - gsi::iterator ("each_overlapping_inst", (db::Cell::overlapping_iterator (db::Cell::*) (const db::Cell::box_type &b) const) &db::Cell::begin_overlapping, gsi::arg ("b"), + gsi::iterator_ext ("each_overlapping_inst", &begin_overlapping_inst, gsi::arg ("b"), "@brief Gets the instances overlapping the given rectangle\n" "\n" "This will iterate over all child cell\n" @@ -2576,7 +2608,7 @@ Class decl_Cell ("db", "Cell", "\n" "Starting with version 0.15, this iterator delivers \\Instance objects rather than \\CellInstArray objects." ) + - gsi::iterator_ext ("each_overlapping_inst", &cell_begin_overlapping_inst_um, gsi::arg ("b"), + gsi::iterator_ext ("each_overlapping_inst", &begin_overlapping_inst_um, gsi::arg ("b"), "@brief Gets the instances overlapping the given rectangle, with the rectangle in micrometer units\n" "\n" "This will iterate over all child cell\n" @@ -2589,7 +2621,7 @@ Class decl_Cell ("db", "Cell", "\n" "This variant has been introduced in version 0.25." ) + - gsi::iterator ("each_touching_inst", (db::Cell::touching_iterator (db::Cell::*) (const db::Cell::box_type &b) const) &db::Cell::begin_touching, gsi::arg ("b"), + gsi::iterator_ext ("each_touching_inst", &begin_touching_inst, gsi::arg ("b"), "@brief Gets the instances touching the given rectangle\n" "\n" "This will iterate over all child cell\n" @@ -2599,7 +2631,7 @@ Class decl_Cell ("db", "Cell", "\n" "Starting with version 0.15, this iterator delivers \\Instance objects rather than \\CellInstArray objects." ) + - gsi::iterator_ext ("each_touching_inst", &cell_begin_touching_inst_um, gsi::arg ("b"), + gsi::iterator_ext ("each_touching_inst", &begin_touching_inst_um, gsi::arg ("b"), "@brief Gets the instances touching the given rectangle, with the rectangle in micrometer units\n" "\n" "This will iterate over all child cell\n" @@ -2612,7 +2644,7 @@ Class decl_Cell ("db", "Cell", "\n" "This variant has been introduced in version 0.25." ) + - gsi::iterator ("each_child_cell", &db::Cell::begin_child_cells, + gsi::iterator_ext ("each_child_cell", &begin_child_cells, "@brief Iterates over all child cells\n" "\n" "This iterator will report the child cell indices, not every instance.\n" @@ -2623,12 +2655,12 @@ Class decl_Cell ("db", "Cell", "The number of child cells (not child instances!) is returned.\n" "CAUTION: this method is SLOW, in particular if many instances are present.\n" ) + - gsi::iterator ("each_inst", (db::Cell::const_iterator (db::Cell::*) () const) &db::Cell::begin, + gsi::iterator_ext ("each_inst", &begin_inst, "@brief Iterates over all child instances (which may actually be instance arrays)\n" "\n" "Starting with version 0.15, this iterator delivers \\Instance objects rather than \\CellInstArray objects." ) + - gsi::iterator ("each_parent_inst", &db::Cell::begin_parent_insts, + gsi::iterator_ext ("each_parent_inst", &begin_parent_insts, "@brief Iterates over the parent instance list (which may actually be instance arrays)\n" "\n" "The parent instances are basically inversions of the instances. Using parent instances " @@ -2639,7 +2671,7 @@ Class decl_Cell ("db", "Cell", "\n" "The number of parent cells (cells which reference our cell) is reported." ) + - gsi::iterator ("each_parent_cell", &db::Cell::begin_parent_cells, &db::Cell::end_parent_cells, + gsi::iterator_ext ("each_parent_cell", &begin_parent_cells, "@brief Iterates over all parent cells\n" "\n" "This iterator will iterate over the parent cells, just returning their\n" diff --git a/src/db/db/gsiDeclDbHelpers.h b/src/db/db/gsiDeclDbHelpers.h new file mode 100644 index 000000000..22b5f5e50 --- /dev/null +++ b/src/db/db/gsiDeclDbHelpers.h @@ -0,0 +1,83 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2019 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_gsiDeclDbHelpers +#define HDR_gsiDeclDbHelpers + +#include "dbLayoutUtils.h" + +namespace gsi +{ + /** + * @brief A safe iterator locking the layout while iterating a container within it + */ + template + class layout_locking_iterator2 + : private db::LayoutLocker + { + public: + typedef typename I::value_type value_type; + typedef typename I::reference reference; + typedef typename I::pointer pointer; + typedef typename I::difference_type difference_type; + typedef typename I::iterator_category iterator_category; + + layout_locking_iterator2 (const db::Layout *layout, const I &b, const I &e) : db::LayoutLocker (const_cast (layout)), m_b (b), m_e (e) {} + bool at_end () const { return m_b == m_e; } + void operator++ () { ++m_b; } + + reference operator* () const { return *m_b; } + pointer operator-> () const { return m_b.operator-> (); } + + private: + I m_b, m_e; + }; + + /** + * @brief A safe iterator locking the layout while iterating a container within it + */ + template + class layout_locking_iterator1 + : private db::LayoutLocker + { + public: + typedef typename I::value_type value_type; + typedef typename I::reference reference; + typedef typename I::pointer pointer; + typedef typename I::difference_type difference_type; + typedef typename I::iterator_category iterator_category; + + layout_locking_iterator1 (const db::Layout *layout, const I &i) : db::LayoutLocker (const_cast (layout)), m_i (i) { } + bool at_end () const { return m_i.at_end (); } + void operator++ () { ++m_i; } + + reference operator* () const { return *m_i; } + pointer operator-> () const { return m_i.operator-> (); } + + private: + I m_i; + }; + +} + +#endif diff --git a/src/db/db/gsiDeclDbShapes.cc b/src/db/db/gsiDeclDbShapes.cc index 08d79b7b0..f422ab20d 100644 --- a/src/db/db/gsiDeclDbShapes.cc +++ b/src/db/db/gsiDeclDbShapes.cc @@ -22,6 +22,8 @@ #include "gsiDecl.h" + +#include "gsiDeclDbHelpers.h" #include "dbShapes.h" #include "dbShape.h" #include "dbLayout.h" @@ -101,54 +103,54 @@ static db::Shape dinsert_with_properties (db::Shapes *s, const Sh &p, db::proper return s->insert (db::object_with_properties (db::CplxTrans (shapes_dbu (s)).inverted () * p, id)); } -static db::Shapes::shape_iterator begin (const db::Shapes *s, unsigned int flags) +static gsi::layout_locking_iterator1 begin (const db::Shapes *s, unsigned int flags) { - return s->begin (flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin (flags)); } -static db::Shapes::shape_iterator begin_all (const db::Shapes *s) +static gsi::layout_locking_iterator1begin_all (const db::Shapes *s) { - return s->begin (db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin (db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_overlapping (const db::Shapes *s, unsigned int flags, const db::Box ®ion) +static gsi::layout_locking_iterator1begin_overlapping (const db::Shapes *s, unsigned int flags, const db::Box ®ion) { - return s->begin_overlapping (region, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (region, flags)); } -static db::Shapes::shape_iterator begin_doverlapping (const db::Shapes *s, unsigned int flags, const db::DBox ®ion) +static gsi::layout_locking_iterator1begin_doverlapping (const db::Shapes *s, unsigned int flags, const db::DBox ®ion) { - return s->begin_overlapping (db::CplxTrans (shapes_dbu (s)).inverted () * region, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (db::CplxTrans (shapes_dbu (s)).inverted () * region, flags)); } -static db::Shapes::shape_iterator begin_overlapping_all (const db::Shapes *s, const db::Box ®ion) +static gsi::layout_locking_iterator1begin_overlapping_all (const db::Shapes *s, const db::Box ®ion) { - return s->begin_overlapping (region, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (region, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_doverlapping_all (const db::Shapes *s, const db::DBox ®ion) +static gsi::layout_locking_iterator1begin_doverlapping_all (const db::Shapes *s, const db::DBox ®ion) { - return s->begin_overlapping (db::CplxTrans (shapes_dbu (s)).inverted () * region, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_overlapping (db::CplxTrans (shapes_dbu (s)).inverted () * region, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_touching (const db::Shapes *s, unsigned int flags, const db::Box ®ion) +static gsi::layout_locking_iterator1begin_touching (const db::Shapes *s, unsigned int flags, const db::Box ®ion) { - return s->begin_touching (region, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (region, flags)); } -static db::Shapes::shape_iterator begin_dtouching (const db::Shapes *s, unsigned int flags, const db::DBox ®ion) +static gsi::layout_locking_iterator1begin_dtouching (const db::Shapes *s, unsigned int flags, const db::DBox ®ion) { - return s->begin_touching (db::CplxTrans (shapes_dbu (s)).inverted () * region, flags); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (db::CplxTrans (shapes_dbu (s)).inverted () * region, flags)); } -static db::Shapes::shape_iterator begin_touching_all (const db::Shapes *s, const db::Box ®ion) +static gsi::layout_locking_iterator1begin_touching_all (const db::Shapes *s, const db::Box ®ion) { - return s->begin_touching (region, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (region, db::ShapeIterator::All)); } -static db::Shapes::shape_iterator begin_dtouching_all (const db::Shapes *s, const db::DBox ®ion) +static gsi::layout_locking_iterator1begin_dtouching_all (const db::Shapes *s, const db::DBox ®ion) { - return s->begin_touching (db::CplxTrans (shapes_dbu (s)).inverted () * region, db::ShapeIterator::All); + return gsi::layout_locking_iterator1 (s->layout (), s->begin_touching (db::CplxTrans (shapes_dbu (s)).inverted () * region, db::ShapeIterator::All)); } static void transform_shapes (db::Shapes *s, const db::Trans &trans) diff --git a/src/laybasic/laybasic/layDitherPattern.cc b/src/laybasic/laybasic/layDitherPattern.cc index f4afad80b..c3fbd3085 100644 --- a/src/laybasic/laybasic/layDitherPattern.cc +++ b/src/laybasic/laybasic/layDitherPattern.cc @@ -726,8 +726,6 @@ DitherPatternInfo::from_strings (const std::vector &strv) uint_from_string (strv [strv.size () - 1 - i].c_str (), data [i], w); } - std::reverse (&data[0], &data[h]); - set_pattern (data, w, h); } diff --git a/src/tl/tl/tlReuseVector.h b/src/tl/tl/tlReuseVector.h index f31236a3a..c7cad2b69 100644 --- a/src/tl/tl/tlReuseVector.h +++ b/src/tl/tl/tlReuseVector.h @@ -887,6 +887,21 @@ public: init (); } + /** + * @brief Returns a value indicating whether the given index is valid + */ + bool is_used (size_type n) const + { + if (n >= first () && n < last ()) { + if (mp_rdata) { + return mp_rdata->is_used (n); + } else { + return true; + } + } + return false; + } + /** * @brief For diagnostics purposes only */ @@ -908,18 +923,6 @@ private: mp_rdata = 0; } - bool is_used (size_type n) const - { - if (n >= first () && n < last ()) { - if (mp_rdata) { - return mp_rdata->is_used (n); - } else { - return true; - } - } - return false; - } - size_type first () const { if (mp_rdata) { diff --git a/testdata/gds/t200.gds b/testdata/gds/t200.gds new file mode 100644 index 000000000..08552d3a4 Binary files /dev/null and b/testdata/gds/t200.gds differ diff --git a/testdata/ruby/dbLayout.rb b/testdata/ruby/dbLayout.rb index 04b418eb9..cb89a9e0d 100644 --- a/testdata/ruby/dbLayout.rb +++ b/testdata/ruby/dbLayout.rb @@ -1994,6 +1994,45 @@ END end + # Iterating while flatten + def test_issue200 + + ly = RBA::Layout.new + ly.read(ENV["TESTSRC"] + "/testdata/gds/t200.gds") + l1 = ly.layer(1, 0) + l2 = ly.layer(2, 0) + l3 = ly.layer(3, 0) + + tc_name = ly.top_cell.name + r1 = RBA::Region::new(ly.top_cell.begin_shapes_rec(l1)) + r2 = RBA::Region::new(ly.top_cell.begin_shapes_rec(l2)) + r3 = RBA::Region::new(ly.top_cell.begin_shapes_rec(l3)) + assert_equal(r1.size > 0, true) + assert_equal(r2.size > 0, true) + assert_equal(r3.size == 0, true) + + ly.top_cell.each_inst do |ci| + ci.flatten + end + + tc = ly.cell(tc_name) + assert_equal(ly.top_cells.size, 4) + assert_equal(tc.child_cells, 0) + assert_equal(tc.parent_cells, 0) + + rr1 = RBA::Region::new(tc.begin_shapes_rec(l1)) + rr2 = RBA::Region::new(tc.begin_shapes_rec(l2)) + rr3 = RBA::Region::new(tc.begin_shapes_rec(l3)) + assert_equal(r1.size, rr1.size) + assert_equal(r2.size, rr2.size) + assert_equal(r3.size, rr3.size) + + assert_equal((rr1 ^ r1).is_empty?, true) + assert_equal((rr2 ^ r2).is_empty?, true) + assert_equal((rr3 ^ r3).is_empty?, true) + + end + end load("test_epilogue.rb")