diff --git a/Changelog b/Changelog
index 23d35b08d..62ecba455 100644
--- a/Changelog
+++ b/Changelog
@@ -1,19 +1,276 @@
-0.27 (2020-xx-xx):
-* Enhancement: %GITHUB%/issues/521
- Enhanced API for ObjectInstPath
+0.27 (2021-04-xx):
+
+* Enhancements: Numerous new functions for the RBA and pya API
+ Some highlights:
+ * "Texts" for text collections (similar for Edges/EdgePairs/Region)
+ * New modes for blending layout files - see GitHub issue #666
+ * New function Cell#transform - see GitHub issue #598
+ * New functions for Image (read, write, clear)
+ * New functions for Region and Edges correlating with the new DRC features
+ * Multi-cell hierarchical copy/move of trees - will maintain shared instances
+ * RBA: iterators are now automatically made available as Enumerable
+ * All functions having a void return specification now return self (allows chaining)
+ * More functions for manipulating selections (LayoutView#select_all etc.)
+ * Spline interpolation code available in new "Utils" namespace
+ * QByteArray support, mapping to Python byte arrays
+ * MainWindow#set_key_bindings, MainWindow#get_key_bindings, MainWindow#set_menu_items_hidden etc.
+ * New class RecursiveInstanceIterator (similar to RecursiveShapeIterator, but acts on instances)
+ * Deep vs. flat operations do not always flatten out now (flat vs. deep does however)
+ * Global transformations for inputs
+* Enhancements: New DRC features
+ Some highlights:
+ * Better support for texts - "text layers"
+ * Combined AND+NOT feature for separating regions into inside and outside part
+ * "max_vertex_count" and "max_area_ratio" configuration options
+ * "forget" for memory optimization
+ * Shielding is optional now for some DRC functions
+ * "interact" now has a count filter
+ * In verbose more, figure counts and more information is printed
+ * Generic DRC function and complex DRC operations: for details search "Universal DRC" in documentation
+ * "not_opposite" and "rect_filter" options for some DRC functions
+ * "enclosing" (selects polygons entirely enclosing others)
+ * New filters for polygons: squares, non_squares, area ratio, bbox aspect ratio
+ * More intuitive specification of projection limits ("projecting < 2.um")
+ * "with_holes" and "without_holes", also with count
+ * Density check is included now ("with_densitiy", "without_density")
+ * "split_..." functions give interacting/non-interacting sets in one step
+ * Better support for generic transformations as Matrix2d and Matrix3d
+ * "fill" and "fill_with_left" functions for dummy fill
+ * NO "connected" feature yet. Sorry. Had to drop it to finish this release.
+* Enhancements: new LVS features
+ Some highlights:
+ * Improved netlist and LVS result browser (infinite-depth browsing)
+ * Improved circuit match algorithm
+ * Case insensitive handling of object names for SPICE netlists
+ * Probe feature fixed in flat mode
+ * "connect_explicit": for details search "connect_explicit" in documentation
+* Enhancements: New features for images
+ Some highlights:
+ * New menu item: show and hide all images - see GitHub issue #535
+ * False color nodes now can have a left and right color allowing color steps
+ * Persistance of images through a special file format: "lyimg" (XML based)
+* Enhancements: LEF/DEF reader
+ Some highlights:
+ * Support for layer map files
+ * More complete spec support (e.g. FILL, MASK, FOREIGN, DO/BY/STEP ...)
+ * Several bug fixes, e.g. routing layer switch for VIAs
+ * Some functions also act on the transient selection (less mouse clicks)
+* Enhancements: Layout editing and rulers
+ Some highlights:
+ * Object properties now are changed without having to commit the dialogs
+ * Dockable editor options windows
+ * "Recently used" list
+ * A "distribute objects" feature (Edit/Selection/Distribute)
+ * Snap highlighting
+ * Mouse tracking cursor indicates grid- and object-snapped location
+* Enhancements: Help browser
+ * Bookmarks
+ * Search in page (Ctrl+F)
+* Enhancement: Improved fill tool
+ The fill tool now also supports skewed fill pattern repetitions
+* Enhancement: Ability to utilize a LayoutView as a Widget
+ Standalone instantiation of a LayoutView object is
+ supported now. So it becomes possible to create
+ custom MainWindow UIs and embed a layout view there.
+* Enhancement: Improved layer and cell list filtering and searching
+* Enhancement: Experimental 3d (called 2.5d) view of layout
+ For details search "2.5d View" in documentation.
+* Enhancement: Improved performance on sea of instances for OASIS files
+ Iterated OASIS instances are stored and handled in a leaner way in viewer mode
+* Enhancement: Buddy scripts can concatenate files with "+" for input
+ Concatenation happens by "blending files". Beware of the risk this implies.
+* Enhancement: Layer maps now support n:m layer mapping
+ This allows mapping n input layers to one logical layer (merging) and also
+ one input layer to m logical ones (clone layer). This applies to the
+ buddy scripts and layer maps inside KLayout's reader.
+* Enhancement: include mechanism for easy include of files into DRC/LVS scripts
+ This is a plain text substitution feature. Don't use it for Ruby or Python
+ scripts (the preferred way is still require/import). But it's a quick way
+ to include partial DRC and LVS scripts without having to worry about variable
+ scope. For details see "Including other files" in the documentation under:
+ KLayout User Manual/Design Rule Check (DRC)/DRC Runsets.
+* Bugfix: %GITHUB%/issues/750
+ PCB gerber import: Incorrect handling of D02 operations.
+* Bugfix: %GITHUB%/issues/740
+ Bug in the "smooth" function.
+* Enhancement: %GITHUB%/issues/691
+ Technology specific libraries: library name resolution based on technology.
+* Enhancement: %GITHUB%/issues/666
+ Controlling the way a layout reader integrates cells into an existing layout.
+* Bugfix: %GITHUB%/issues/663
+ Deep mode DRC: separation from "inside" gives wrong errors.
+* Enhancement: %GITHUB%/issues/648
+ LVS could not do "connect_implicit" with global nets.
+* Bugfix: %GITHUB%/issues/609
+ Internal error on net extraction.
+* Enhancement: %GITHUB%/issues/598
+ Plain transformation of cell missing.
+* Enhancement: %GITHUB%/issues/588
+ RBA/PYA: Provide event when a net is selected in the netlist browser.
+* Enhancement: %GITHUB%/issues/563
+ True support for text objects in DRC/LVS (text layers).
* Enhancement: %GITHUB%/issues/558
Edges#extents, Texts#extents and EdgePairs#extents now
work hierarchically in deep mode. In DRC, this means,
"extents" is a deep-enabled method now.
-* Enhancement: %GITHUB%/issues/563
- True support for text objects in DRC/LVS (text layers)
-* Enhancement: ability to utilize a LayoutView as a Widget
- Standalone instantiation of a LayoutView object is
- supported now. So it becomes possible to create
- custom MainWindow UIs and embed a layout view there.
+* Enhancement: %GITHUB%/issues/535
+ Image handling enhancements.
+* Enhancement: %GITHUB%/issues/521
+ Enhanced API for ObjectInstPath.
+* Enhancement: %GITHUB%/issues/487
+ Difficult to select specific labels for net name assignment in net extraction.
+ Solution involves a more elaborate handling of texts through "text layers.
-0.26.5 (2020-xx-xx):
+0.26.11 (2021-02-27):
+
+* Bugfix: %GITHUB%/issues/733
+ Relative path resolution in session files fails when the session file's path contains "+" characters
+* Enhancement: %GITHUB%/issues/730
+ Support of class 'QUiLoader' in PYA and RBA
+* Bugfix: %GITHUB%/issues/728
+ Fails to build on Debian hppa: uses non-standard sa_restorer field of struct sigaction
+* Bugfix: %GITHUB%/issues/726
+ Crash on LayoutView#clear_selection on Linux.
+* Bugfix: %GITHUB%/issues/723
+ Backup scheme wasn't working correctly with a single file without path
+ given as command line argument.
+
+0.26.10 (2020-02-02):
+
+* Enhancement: %GITHUB%/issues/720
+ "Safe save" and backups: when saving files, the file is only overwritten after
+ the save terminated successfully. This will avoid loss of data for full volumes
+ or network share dropouts. In addition, a configurable number of back files can
+ be kept (see File/Setup: Application/General).
+* Bugfix: %GITHUB%/issues/718
+ GDS export issue fixed (breaking of polygons was filling holes)
+* Bugfix: %GITHUB%/issues/709
+ LVS compare enters infinite loop when it encounters two entirely identical subcircuits
+* Bugfix: %GITHUB%/issues/708
+ Qt binding: missing support for binary strings as QByteArray representative
+* Bugfix: %GITHUB%/issues/707
+ QJsonValue's string constructor is ambiguous
+* Bugfix: %GITHUB%/issues/704
+ Rational Splines not supported DXF
+* Bugfix: %GITHUB%/issues/693
+ MAGIC files won't find subcells when reading from command line
+* Bugfix: HTTP stream reading issue with redirect
+ At least on MacOS a segfault happened when reading HTTP stream data
+ (e.g. for package manager) from addresses which are redirected.
+* Enhancement: Removed %APPDATA% from DLL search path on Windows
+ This will avoid installation poisoning by the one from %APPDATA%
+ (which ironically is the default installation path). Eventually
+ multiple versions can be used in parallel.
+
+0.26.9 (2020-11-27):
+
+* Bugfix: %GITHUB%/issues/658
+ Menu items were not put into the right place on MacOS.
+* Bugfix: %GITHUB%/issues/652
+ "M" factor scaling was not working for Spice reader.
+* Bugfix: %GITHUB%/issues/651
+ Fixed an issue with DRC "select".
+* Bugfix: %GITHUB%/issues/647
+ Text orientation was not considered properly in search & replace
+* Bugfix: %GITHUB%/issues/646
+ A potential crash was fixed happening when a PCell
+ library is deleted
+* Bugfix: Display bug
+ Cell placements with small magnification factors (such that the
+ viewport dimensions exceeded the DBU space when seem from inside
+ the cell) lead to display errors.
+
+0.26.8 (2020-09-15):
+
+* Enhancement: %GITHUB%/issues/639
+ A new method is available which enables copying of multiple cells
+ into a target layout while maintaining common subcells are single
+ cells.
+* Bugfix: %GITHUB%/issues/637
+ Points have not been selected properly when inside mirrored subcells
+ in partial edit mode.
+* Bugfix: %GITHUB%/issues/629
+ Qt5 QTimer timeout signal was not available to Python or Ruby.
+ This also applied to all "private" signals of Qt5. QTimer is just
+ one important example for this case.
+* Bugfix: %GITHUB%/issues/617
+ A problem with pseudo-const Python/Ruby objects in the netlist API
+ was fixed.
+* Bugfix: %GITHUB%/issues/615
+ Basic authentication for package manager now uses UTF-8 encoding.
+ Most servers expect this kind of encoding today. UTF password
+ characters are supported this way.
+
+0.26.7 (2020-07-07):
+
+* Bugfix: %GITHUB%/issues/381 and more
+ Some bugs fixed that happened specifically on MacOS.
+ 1.) A segfault that happened in LVS
+ 2.) Some classes were not properly registered for usage in scripts.
+* Bugfix: %GITHUB%/issues/493
+ LVS asserted on MacOS
+* Enhancement: %GITHUB%/issues/586
+ As a safety feature, the stream writers now refuse to write layouts
+ with cells carrying the same names. Writing such layers would result
+ in corrupted or invalid layout files.
+* Bugfix: %GITHUB%/issues/589 (tentative)
+ On Anaconda-based builds for MacOS 10.15 (Catalina) a loss of instances
+ was observed. This could be traced down to compiler/library incompatibilities
+ but not further.
+* Enhancements: %GITHUB%/issues/591
+ Two enhancements in the macro editor:
+ 1.) A crash happening when adding a new location was fixed
+ 2.) The template selection popup can now be disabled by dismissing the
+ tip dialog.
+* Bugfix: %GITHUB%/issues/592
+ Reading a file into a layout with unnamed layers caused problems with
+ layer mapping specs.
+* Bugfix: %GITHUB%/issues/596
+ Library#_destroy was crashing the application. As this function must not
+ be called, it's rerouted to "nothing" for backward compatibility.
+* Enhancement: %GITHUB%/issues/603
+ The "adjust origin" feature now allows specifying the target
+ coordinates for the adjustment.
+* Bugfix: %GITHUB%/issues/610
+ An internal error happened for certain hierarchical configurations on
+ netlist extraction.
+* Enhancement: LVS netlist compare
+ The algorithm was improved to provide better reproducibility. The
+ detection of matching paths in the presence of ambiguities was
+ improved.
+ In addition, the netlist compare now favours net names for resolving
+ ambiguities. So if nets are named the same in the layout and the
+ schematic, ambiguities are resolved based on these names. This is
+ usually more efficient. A new function is available to turn this
+ feature off: "consider_net_names(false)".
+
+0.26.6 (2020-06-05):
+
+* Enhancement: %GITHUB%/issues/522
+ Skip comment lines with // in RVE DB reader
+* Bugfix: %GITHUB%/issues/547
+ Doc fixes, better error messages on some Shape methods
+* Bugfix: %GITHUB%/issues/554
+ Using 64bit coordinates on RVE reader to avoid overflow
+* Bugfix: %GITHUB%/issues/565
+ Spice reader: .global should not add pin if the signal
+ isn't used in a subcircuit
+* Bugfix: %GITHUB%/issues/568 and %GITHUB%/issues/578
+ A CIF reader and writer bug was fixed
+* Bugfix: %GITHUB%/issues/570 and %GITHUB%/issues/579
+ Perimenter can be included in antenna area for the
+ antenna check. This also includes a mode in which only
+ the perimeter is considered.
+* Enhancement: %GITHUB%/issues/560
+ A library can be associated with multiple technologies now.
+* Bugfix: width of cell and library side panels could not be
+ reduced below the width of the selection boxes in the
+ header
+* Bugfix: cell view selection header text did not get updated
+ when saving the layout to a different file
+
+0.26.5 (2020-05-02):
* Bugfix: %GITHUB%/issues/539
An internal error happened on netlist flatten sometimes
@@ -28,6 +285,8 @@
* Bugfix: %GITHUB%/issues/544
Duplicate .global statements in SPICE netlists created
duplicate pins
+* Bugfix: %GITHUB%/issues/548
+ A shielding issue was fixed for DRC space measurements
* Bugfix: diff tool bug with paths
Differences in path points where no reported
* Enhancement: documentation clarifications and typos fixed
diff --git a/src/ant/ant/antPropertiesPage.cc b/src/ant/ant/antPropertiesPage.cc
index 721cd8c24..98bb0fcd5 100644
--- a/src/ant/ant/antPropertiesPage.cc
+++ b/src/ant/ant/antPropertiesPage.cc
@@ -122,7 +122,6 @@ PropertiesPage::swap_points_clicked ()
y1->setText (ty1);
y2->setText (ty2);
- db::Transaction t (manager (), tl::to_string (QObject::tr ("Swap ruler points")));
emit edited ();
}
@@ -224,7 +223,6 @@ PropertiesPage::snap_to_layout_clicked ()
y2->setText (ys);
}
- db::Transaction t (manager (), tl::to_string (snap_p1 ? QObject::tr ("Snap first ruler point") : QObject::tr ("Snap second ruler point")));
emit edited ();
break;
@@ -249,7 +247,6 @@ PropertiesPage::snap_to_layout_clicked ()
x2->setText (tl::to_qstring (tl::micron_to_string (ee.second.x ())));
y2->setText (tl::to_qstring (tl::micron_to_string (ee.second.y ())));
- db::Transaction t (manager (), tl::to_string (QObject::tr ("Snap both ruler points")));
emit edited ();
}
diff --git a/src/ant/ant/antService.cc b/src/ant/ant/antService.cc
index e5d74cef7..f9666fd2c 100644
--- a/src/ant/ant/antService.cc
+++ b/src/ant/ant/antService.cc
@@ -1274,8 +1274,9 @@ Service::end_move (const db::DPoint &, lay::angle_constraint_type)
// compute moved object and replace
ant::Object *rnew = new ant::Object (*robj);
rnew->transform (m_trans);
+ int new_id = rnew->id ();
mp_view->annotation_shapes ().replace (s->first, db::DUserObject (rnew));
- annotation_changed_event (rnew->id ());
+ annotation_changed_event (new_id);
}
diff --git a/src/db/db/dbBoxTree.h b/src/db/db/dbBoxTree.h
index acd9c37a2..cc687ca54 100644
--- a/src/db/db/dbBoxTree.h
+++ b/src/db/db/dbBoxTree.h
@@ -760,6 +760,15 @@ public:
// .. nothing else ..
}
+ /**
+ * @brief Move constructor
+ */
+ box_tree (box_tree &&b)
+ : m_objects (b.m_objects), m_elements (b.m_elements), mp_root (b.mp_root)
+ {
+ b.mp_root = 0;
+ }
+
/**
* @brief Assignment
*/
@@ -774,6 +783,21 @@ public:
return *this;
}
+ /**
+ * @brief Assignment (move)
+ */
+ box_tree &operator= (box_tree &&b)
+ {
+ clear ();
+ m_objects = b.m_objects;
+ m_elements = b.m_elements;
+ if (b.mp_root) {
+ mp_root = b.mp_root;
+ b.mp_root = 0;
+ }
+ return *this;
+ }
+
/**
* @brief The destructor
*/
@@ -1729,6 +1753,15 @@ public:
// .. nothing else ..
}
+ /**
+ * @brief Move constructor
+ */
+ unstable_box_tree (unstable_box_tree &&b)
+ : m_objects (b.m_objects), mp_root (b.mp_root)
+ {
+ b.mp_root = 0;
+ }
+
/**
* @brief Assignment
*/
@@ -1742,6 +1775,20 @@ public:
return *this;
}
+ /**
+ * @brief Assignment (move)
+ */
+ unstable_box_tree &operator= (unstable_box_tree &&b)
+ {
+ clear ();
+ m_objects = b.m_objects;
+ if (b.mp_root) {
+ mp_root = b.mp_root;
+ b.mp_root = 0;
+ }
+ return *this;
+ }
+
/**
* @brief The destructor
*/
diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc
index db4aedd84..e3e9b8d7c 100644
--- a/src/db/db/dbCompoundOperation.cc
+++ b/src/db/db/dbCompoundOperation.cc
@@ -357,10 +357,7 @@ CompoundRegionMultiInputOperationNode::init ()
CompoundRegionMultiInputOperationNode::~CompoundRegionMultiInputOperationNode ()
{
- for (tl::shared_collection::iterator i = m_children.begin (); i != m_children.end (); ++i) {
- delete i.operator-> ();
- }
- m_children.clear ();
+ // .. nothing yet ..
}
void
diff --git a/src/db/db/dbD25TechnologyComponent.cc b/src/db/db/dbD25TechnologyComponent.cc
index 2719bfbb7..62f9b24e4 100644
--- a/src/db/db/dbD25TechnologyComponent.cc
+++ b/src/db/db/dbD25TechnologyComponent.cc
@@ -119,6 +119,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
// provide some explanation for the initialization
m_src =
"# Provide z stack information here\n"
+ "#\n"
"# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\n"
"# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n"
"# Named arguments are:\n"
@@ -127,7 +128,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
"# zstop The upper z position of the extruded layer in µm\n"
"# height The height of the extruded layer in µm\n"
"#\n"
- "# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart', "
+ "# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart',\n"
"# the upper level of the previous layer will be used.\n"
"#\n"
"# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\n"
@@ -139,25 +140,52 @@ D25TechnologyComponent::D25TechnologyComponent ()
"# 1: zstop=1.5, zstart=0.5 # same with named parameters\n"
"# 1: height=1.0, zstop=1.5 # same with z stop minus height\n"
"# 1: 1.0 zstop=1.5 # same with height as unnamed parameter\n"
+ "#\n"
+ "# VARIABLES\n"
+ "#\n"
+ "# You can declare variables with:\n"
+ "# var name = value\n"
+ "#\n"
+ "# You can use variables inside numeric expressions.\n"
+ "# Example:\n"
+ "# var hmetal = 0.48\n"
+ "# 7/0: 0.5 0.5+hmetal*2 # 2x thick metal\n"
+ "#\n"
+ "# You cannot use variables inside layer specifications currently.\n"
+ "#\n"
+ "# CONDITIONALS\n"
+ "#\n"
+ "# You can enable or disable branches of the table using 'if', 'else', 'elseif' and 'end':\n"
+ "# Example:\n"
+ "# var thick_m1 = true\n"
+ "# if thickm1\n"
+ "# 1: 0.5 1.5\n"
+ "# else\n"
+ "# 1: 0.5 1.2\n"
+ "# end\n"
+ "\n"
;
}
D25TechnologyComponent::D25TechnologyComponent (const D25TechnologyComponent &d)
: db::TechnologyComponent (d25_component_name (), d25_description ())
{
- m_layers = d.m_layers;
m_src = d.m_src;
}
-void
-D25TechnologyComponent::compile_from_source (const std::string &src)
+D25TechnologyComponent::layers_type
+D25TechnologyComponent::compile_from_source () const
{
+ layers_type layers;
+
int current_line = 0;
- m_layers.clear ();
try {
- std::vector lines = tl::split (src, "\n");
+ tl::Eval eval;
+ std::vector conditional_stack;
+
+ std::vector lines = tl::split (m_src, "\n");
for (std::vector::const_iterator l = lines.begin (); l != lines.end (); ++l) {
++current_line;
@@ -168,12 +196,86 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
// ignore comments
} else if (ex.at_end ()) {
// ignore empty lines
+
+ } else if (ex.test ("if")) {
+
+ tl::Expression x;
+ eval.parse (x, ex);
+ conditional_stack.push_back (x.execute ().to_bool ());
+
+ ex.expect_end ();
+
+ } else if (ex.test ("else")) {
+
+ if (conditional_stack.empty ()) {
+ throw tl::Exception (tl::to_string (tr ("'else' without 'if'")));
+ }
+
+ conditional_stack.back () = ! conditional_stack.back ();
+
+ ex.expect_end ();
+
+ } else if (ex.test ("end")) {
+
+ if (conditional_stack.empty ()) {
+ throw tl::Exception (tl::to_string (tr ("'end' without 'if'")));
+ }
+
+ conditional_stack.pop_back ();
+
+ ex.expect_end ();
+
+ } else if (ex.test ("elsif")) {
+
+ if (conditional_stack.empty ()) {
+ throw tl::Exception (tl::to_string (tr ("'elsif' without 'if'")));
+ }
+
+ tl::Expression x;
+ eval.parse (x, ex);
+ conditional_stack.back () = x.execute ().to_bool ();
+
+ ex.expect_end ();
+
+ } else if (! conditional_stack.empty () && ! conditional_stack.back ()) {
+
+ continue;
+
+ } else if (ex.test ("var")) {
+
+ std::string n;
+ ex.read_name (n);
+
+ ex.expect ("=");
+
+ tl::Expression x;
+ eval.parse (x, ex);
+ eval.set_var (n, x.execute ());
+
+ ex.expect_end ();
+
+ } else if (ex.test ("print")) {
+
+ tl::Expression x;
+ eval.parse (x, ex);
+ ex.expect_end ();
+
+ tl::info << x.execute ().to_string ();
+
+ } else if (ex.test ("error")) {
+
+ tl::Expression x;
+ eval.parse (x, ex);
+ ex.expect_end ();
+
+ throw tl::Exception (x.execute ().to_string ());
+
} else {
db::D25LayerInfo info;
- if (! m_layers.empty ()) {
- info.set_zstart (m_layers.back ().zstop ());
- info.set_zstop (m_layers.back ().zstop ());
+ if (! layers.empty ()) {
+ info.set_zstart (layers.back ().zstop ());
+ info.set_zstop (layers.back ().zstop ());
}
tl::Variant z0, z1, h;
@@ -191,16 +293,18 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
break;
}
- double pv = 0.0;
+ tl::Expression pvx;
std::string pn;
if (ex.try_read_name (pn)) {
ex.expect ("=");
- ex.read (pv);
+ eval.parse (pvx, ex);
} else {
- ex.read (pv);
+ eval.parse (pvx, ex);
}
+ double pv = pvx.execute ().to_double ();
+
ex.test (",");
if (pn.empty ()) {
@@ -220,7 +324,7 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
if (args.size () == 0) {
if (z0.is_nil () && z1.is_nil ()) {
if (! h.is_nil ()) {
- info.set_zstop (info.zstart () + h.to_double ());
+ info.set_zstop (info.zstop () + h.to_double ());
}
} else if (z0.is_nil ()) {
info.set_zstop (z1.to_double ());
@@ -239,28 +343,28 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
} else if (args.size () == 1) {
if (! h.is_nil ()) {
if (! z0.is_nil ()) {
- throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
+ throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
}
if (! z1.is_nil ()) {
- throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
+ throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
}
info.set_zstart (args[0]);
info.set_zstop (args[0] + h.to_double ());
} else {
if (! z1.is_nil ()) {
- throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
+ throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
}
info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]);
}
} else if (args.size () == 2) {
if (! z0.is_nil ()) {
- throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
+ throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
}
if (! z1.is_nil ()) {
- throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop already given")));
+ throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop already given")));
}
if (! h.is_nil ()) {
- throw tl::Exception (tl::to_string (tr ("Rundundant parameters: height implicitly given")));
+ throw tl::Exception (tl::to_string (tr ("Redundant parameters: height implicitly given")));
}
info.set_zstart (args[0]);
info.set_zstop (args[1]);
@@ -268,25 +372,30 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
throw tl::Exception (tl::to_string (tr ("Too many parameters (max 2)")));
}
- m_layers.push_back (info);
+ layers.push_back (info);
}
}
+ if (! conditional_stack.empty ()) {
+ throw tl::Exception (tl::to_string (tr ("'if', 'else' or 'elsif' without matching 'end'")));
+ }
+
} catch (tl::Exception &ex) {
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
}
- m_src = src;
+ return layers;
}
std::string
D25TechnologyComponent::to_string () const
{
+ layers_type layers = compile_from_source ();
std::string res;
- for (const_iterator i = begin (); i != end (); ++i) {
+ for (layers_type::const_iterator i = layers.begin (); i != layers.end (); ++i) {
if (! res.empty ()) {
res += "\n";
}
@@ -317,11 +426,6 @@ public:
virtual tl::XMLElementBase *xml_element () const
{
return new db::TechnologyComponentXMLElement (d25_component_name (),
- tl::make_element ((D25TechnologyComponent::const_iterator (D25TechnologyComponent::*) () const) &D25TechnologyComponent::begin, (D25TechnologyComponent::const_iterator (D25TechnologyComponent::*) () const) &D25TechnologyComponent::end, &D25TechnologyComponent::add, "layer",
- tl::make_member (&D25LayerInfo::layer_as_string, &D25LayerInfo::set_layer_from_string, "layer") +
- tl::make_member (&D25LayerInfo::zstart, &D25LayerInfo::set_zstart, "zstart") +
- tl::make_member (&D25LayerInfo::zstop, &D25LayerInfo::set_zstop, "zstop")
- ) +
tl::make_member (&D25TechnologyComponent::src, &D25TechnologyComponent::set_src, "src")
);
}
diff --git a/src/db/db/dbD25TechnologyComponent.h b/src/db/db/dbD25TechnologyComponent.h
index 5e4a1d51f..3beade105 100644
--- a/src/db/db/dbD25TechnologyComponent.h
+++ b/src/db/db/dbD25TechnologyComponent.h
@@ -76,55 +76,8 @@ public:
D25TechnologyComponent (const D25TechnologyComponent &d);
typedef std::list layers_type;
- typedef layers_type::const_iterator const_iterator;
- typedef layers_type::iterator iterator;
- void compile_from_source (const std::string &src);
-
- const_iterator begin () const
- {
- return m_layers.begin ();
- }
-
- iterator begin ()
- {
- return m_layers.begin ();
- }
-
- const_iterator end () const
- {
- return m_layers.end ();
- }
-
- iterator end ()
- {
- return m_layers.end ();
- }
-
- void clear ()
- {
- m_layers.clear ();
- }
-
- void erase (iterator p)
- {
- m_layers.erase (p);
- }
-
- void insert (iterator p, const D25LayerInfo &info)
- {
- m_layers.insert (p, info);
- }
-
- void add (const D25LayerInfo &info)
- {
- m_layers.push_back (info);
- }
-
- size_t size () const
- {
- return m_layers.size ();
- }
+ layers_type compile_from_source () const;
const std::string &src () const
{
@@ -145,7 +98,6 @@ public:
}
private:
- layers_type m_layers;
std::string m_src;
};
diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc
index 855be54b5..a684bc149 100644
--- a/src/db/db/dbFillTool.cc
+++ b/src/db/db/dbFillTool.cc
@@ -212,11 +212,6 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0")));
}
- // disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box
- if (enhanced_fill && ! glue_box.empty () && ! fp0.box ().enlarged (db::Vector (1, 1)).inside (glue_box)) {
- enhanced_fill = false;
- }
-
db::Vector kernel_origin (fc_bbox.left (), fc_bbox.bottom ());
std::vector filled_regions;
@@ -256,13 +251,21 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
continue;
}
- size_t ninsts = 0;
+ // disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box
+ bool ef = enhanced_fill;
+ if (ef && ! glue_box.empty () && ! fp->box ().enlarged (db::Vector (1, 1)).inside (glue_box)) {
+ ef = false;
+ }
+ // pick a heuristic "good" starting point in enhanced mode
+ // TODO: this is a pretty weak optimization.
db::Point o = origin;
- if (enhanced_fill) {
+ if (ef) {
o = fp->hull () [0];
}
+ size_t ninsts = 0;
+
GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ());
for (unsigned int i = 0; i < am.area_maps (); ++i) {
@@ -454,7 +457,7 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell
DB_PUBLIC void
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
- const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
+ const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
const db::Region *fill_region = &fr;
@@ -468,7 +471,7 @@ fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fi
++iteration;
remaining.clear ();
- fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, origin, true, &remaining, fill_margin, remaining_polygons, iteration, glue_box);
+ fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration, glue_box);
new_fill_region.swap (remaining);
fill_region = &new_fill_region;
diff --git a/src/db/db/dbFillTool.h b/src/db/db/dbFillTool.h
index a6b5c905c..e3e060514 100644
--- a/src/db/db/dbFillTool.h
+++ b/src/db/db/dbFillTool.h
@@ -118,6 +118,6 @@ fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell
DB_PUBLIC void
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
- const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Point &origin = db::Point (), const db::Box &glue_box = db::Box ());
+ const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Box &glue_box = db::Box ());
}
diff --git a/src/db/db/dbLayer.h b/src/db/db/dbLayer.h
index 2f54619f6..453c8648f 100644
--- a/src/db/db/dbLayer.h
+++ b/src/db/db/dbLayer.h
@@ -107,6 +107,14 @@ struct layer
operator= (d);
}
+ /**
+ * @brief The move constructor
+ */
+ layer (const layer &&d)
+ {
+ operator= (d);
+ }
+
/**
* @brief The assignment operator
*
@@ -123,6 +131,20 @@ struct layer
return *this;
}
+ /**
+ * @brief The assignment operator (move semantics)
+ */
+ layer &operator= (const layer &&d)
+ {
+ if (&d != this) {
+ m_box_tree = d.m_box_tree;
+ m_bbox = d.m_bbox;
+ m_bbox_dirty = d.m_bbox_dirty;
+ m_tree_dirty = d.m_tree_dirty;
+ }
+ return *this;
+ }
+
/**
* @brief Get the iterator for an object given by a pointer
*/
@@ -207,6 +229,18 @@ struct layer
return m_box_tree.insert (sh);
}
+ /**
+ * @brief Insert a new shape object (move semantics)
+ */
+ iterator insert (const Sh &&sh)
+ {
+ // inserting will make the bbox and the tree "dirty" - i.e.
+ // it will need to be updated.
+ m_bbox_dirty = true;
+ m_tree_dirty = true;
+ return m_box_tree.insert (sh);
+ }
+
/**
* @brief Replace the given element with a new one
*
@@ -228,6 +262,19 @@ struct layer
return *ncpos;
}
+ /**
+ * @brief Replace the given element with a new one (move semantics)
+ */
+ Sh &replace (iterator pos, const Sh &&sh)
+ {
+ m_bbox_dirty = true;
+ m_tree_dirty = true;
+ non_const_iterator ncpos;
+ to_non_const_box_tree_iter (pos, ncpos, StableTag ());
+ *ncpos = sh;
+ return *ncpos;
+ }
+
/**
* @brief Erasing of an element
*
diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc
index 808133e68..6d37ab289 100644
--- a/src/db/db/dbPolygonTools.cc
+++ b/src/db/db/dbPolygonTools.cc
@@ -1626,7 +1626,7 @@ AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, const db::Vecto
m_ny = ny;
if (mp_av) {
- delete mp_av;
+ delete[] mp_av;
}
mp_av = new area_type [nx * ny];
diff --git a/src/db/db/dbRegionUtils.h b/src/db/db/dbRegionUtils.h
index f1da9196d..a7e67ce61 100644
--- a/src/db/db/dbRegionUtils.h
+++ b/src/db/db/dbRegionUtils.h
@@ -558,7 +558,7 @@ public:
virtual void process (const db::Polygon &poly, std::vector &res) const;
virtual const TransformationReducer *vars () const { return 0; }
- virtual bool result_is_merged () const { return true; } // we believe so ...
+ virtual bool result_is_merged () const { return false; } // isn't merged for nested holes :(
virtual bool requires_raw_input () const { return false; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
@@ -577,7 +577,7 @@ public:
virtual void process (const db::Polygon &poly, std::vector &res) const;
virtual const TransformationReducer *vars () const { return 0; }
- virtual bool result_is_merged () const { return true; } // we believe so ...
+ virtual bool result_is_merged () const { return false; } // isn't merged for nested hulls :(
virtual bool requires_raw_input () const { return false; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
diff --git a/src/db/db/dbUserObject.h b/src/db/db/dbUserObject.h
index 8961480ba..f9a3c0b92 100644
--- a/src/db/db/dbUserObject.h
+++ b/src/db/db/dbUserObject.h
@@ -206,6 +206,18 @@ public:
}
}
+ /**
+ * @brief The move constructor
+ */
+ user_object (user_object &&d)
+ : mp_obj (0)
+ {
+ if (d.mp_obj) {
+ set_ptr (d.mp_obj);
+ d.mp_obj = 0;
+ }
+ }
+
/**
* @brief Assignment operator
*/
@@ -219,6 +231,20 @@ public:
return *this;
}
+ /**
+ * @brief Assignment operator (move)
+ */
+ user_object &operator= (user_object &&d)
+ {
+ if (d.mp_obj) {
+ set_ptr (d.mp_obj);
+ d.mp_obj = 0;
+ } else {
+ set_ptr (0);
+ }
+ return *this;
+ }
+
/**
* @brief The destructor
*/
diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc
index 6681da3f8..8fb411341 100644
--- a/src/db/db/gsiDeclDbCell.cc
+++ b/src/db/db/gsiDeclDbCell.cc
@@ -1312,9 +1312,9 @@ fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill
static void
fill_region_multi (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
- const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
+ const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
- db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box);
+ db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
}
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
@@ -1881,7 +1881,6 @@ Class decl_Cell ("db", "Cell",
gsi::arg ("column_step"),
gsi::arg ("fill_margin", db::Vector ()),
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
- gsi::arg ("origin", db::Point ()),
gsi::arg ("glue_box", db::Box ()),
"@brief Fills the given region with cells of the given type in enhanced mode with iterations\n"
"This version operates like \\fill_region, but repeats the fill generation until no further fill cells can be placed. "
diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc
index 898e01120..c8ee01b40 100644
--- a/src/db/db/gsiDeclDbRegion.cc
+++ b/src/db/db/gsiDeclDbRegion.cc
@@ -730,9 +730,9 @@ fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill
static void
fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
- const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
+ const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
- db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box);
+ db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
}
static db::Point default_origin;
@@ -2921,7 +2921,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
gsi::arg ("column_step"),
gsi::arg ("fill_margin", db::Vector ()),
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
- gsi::arg ("origin", db::Point ()),
gsi::arg ("glue_box", db::Box ()),
"@brief A mapping of \\Cell#fill_region to the Region class\n"
"\n"
diff --git a/src/db/unit_tests/dbCompoundOperationTests.cc b/src/db/unit_tests/dbCompoundOperationTests.cc
index a465fc28f..a0d305afa 100644
--- a/src/db/unit_tests/dbCompoundOperationTests.cc
+++ b/src/db/unit_tests/dbCompoundOperationTests.cc
@@ -99,6 +99,7 @@ void run_test1 (tl::TestBase *_this, bool deep)
unsigned int l1002 = ly.get_layer (db::LayerProperties (1002, 0));
res.insert_into (&ly, *ly.begin_top_down (), l1002);
+ primary = new db::CompoundRegionOperationPrimaryNode ();
db::CompoundRegionCheckOperationNode space_check (primary, db::SpaceRelation, false /*==all polygons*/, 1050, check_options);
res = r.cop_to_edge_pairs (space_check);
diff --git a/src/db/unit_tests/dbD25TechnologyComponentTests.cc b/src/db/unit_tests/dbD25TechnologyComponentTests.cc
index 76080ef09..b83365ea4 100644
--- a/src/db/unit_tests/dbD25TechnologyComponentTests.cc
+++ b/src/db/unit_tests/dbD25TechnologyComponentTests.cc
@@ -30,44 +30,73 @@ TEST(1)
{
db::D25TechnologyComponent comp;
- comp.compile_from_source ("1/0: 1.0 1.5 # a comment");
+ comp.set_src ("1/0: 1.0 1.5 # a comment");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
- comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5");
+ comp.set_src ("1/0: zstart=1.0 zstop=1.5");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
- comp.compile_from_source ("1/0: zstart=1.0 height=0.5");
+ comp.set_src ("1/0: zstart=1.0 height=0.5");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
- comp.compile_from_source ("1/0: 1.0 height=0.5");
+ comp.set_src ("1/0: 1.0 height=0.5");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
- comp.compile_from_source ("1/0: zstop=1.5 height=0.5");
+ comp.set_src ("1/0: zstop=1.5 height=0.5");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
- comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5\nname: height=3");
+ comp.set_src ("1/0: zstart=1.0 zstop=1.5\nname: height=3");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=1.5, zstop=4.5");
- comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5\nname: zstart=4.0 height=3\n\n# a comment line");
+ comp.set_src ("1/0: zstart=1.0 zstop=1.5\nname: zstart=4.0 height=3\n\n# a comment line");
+ comp.compile_from_source ();
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
+ comp.set_src ("var x=1.0\n1/0: zstart=x zstop=x+0.5\nname: zstart=4.0 height=3\n\n# a comment line");
+ comp.compile_from_source ();
+ EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
+
+ comp.set_src ("var x=1.0\nif x == 1.0\n1/0: zstart=x zstop=x+0.5\nelse\n1/0: zstart=0 zstop=0\nend\nname: zstart=4.0 height=3\n\n# a comment line");
+ comp.compile_from_source ();
+ EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
+
+ comp.set_src ("var x=2.0\nif x == 1.0\n1/0: zstart=x zstop=x+0.5\nelse\n1/0: zstart=0 zstop=0\nend\nname: zstart=4.0 height=3\n\n# a comment line");
+ comp.compile_from_source ();
+ EXPECT_EQ (comp.to_string (), "1/0: zstart=0, zstop=0\nname: zstart=4, zstop=7");
+
try {
- comp.compile_from_source ("blabla");
+ comp.set_src ("blabla");
+ comp.compile_from_source ();
EXPECT_EQ (false, true);
} catch (...) { }
try {
- comp.compile_from_source ("1/0: 1 2 3");
+ comp.set_src ("1/0: 1 2 3");
+ comp.compile_from_source ();
EXPECT_EQ (false, true);
} catch (...) { }
try {
- comp.compile_from_source ("1/0: foo=1 bar=2");
+ comp.set_src ("1/0: foo=1 bar=2");
+ comp.compile_from_source ();
EXPECT_EQ (false, true);
} catch (...) { }
try {
- comp.compile_from_source ("1/0: 1;2");
+ comp.set_src ("1/0: 1;*2");
+ comp.compile_from_source ();
+ EXPECT_EQ (false, true);
+ } catch (...) { }
+
+ try {
+ comp.set_src ("error 42");
+ comp.compile_from_source ();
EXPECT_EQ (false, true);
} catch (...) { }
}
diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc
index 46b57bf22..f02a2f1db 100644
--- a/src/db/unit_tests/dbDeepRegionTests.cc
+++ b/src/db/unit_tests/dbDeepRegionTests.cc
@@ -694,8 +694,8 @@ TEST(10_HullsAndHoles)
db::Region hulls = r1_sized.hulls ();
db::Region holes = r1_sized.holes ();
- EXPECT_EQ (hulls.is_merged (), true);
- EXPECT_EQ (holes.is_merged (), true);
+ EXPECT_EQ (hulls.is_merged (), false);
+ EXPECT_EQ (holes.is_merged (), false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb
index d7cd228ed..9a3d2eefb 100644
--- a/src/drc/drc/built-in-macros/_drc_engine.rb
+++ b/src/drc/drc/built-in-macros/_drc_engine.rb
@@ -259,6 +259,10 @@ module DRC
DRCFillOrigin::new
end
+ def multi_origin
+ DRCFillOrigin::new(nil, nil, true)
+ end
+
def origin(x, y)
DRCFillOrigin::new(x, y)
end
diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb
index 489f2da3a..4d22374b8 100644
--- a/src/drc/drc/built-in-macros/_drc_layer.rb
+++ b/src/drc/drc/built-in-macros/_drc_layer.rb
@@ -4251,7 +4251,9 @@ CODE
# @li @b origin(x, y) @/b: specifies a fixed point to align the pattern with. This point specifies the location
# of the reference point for one pattern cell. @/li
# @li @b auto_origin @/b: lets the algorithm choose the origin. This may result is a slightly better fill coverage
- # as the algorithm is able to determine a pattern origin per fill island. @/li
+ # as the algorithm is able to determine a pattern origin per island to fill. @/li
+ # @li @b multi_origin @/b: lets the algorithm choose the origin and repeats the fill with different origins
+ # until no further fill cell can be fitted. @/li
# @li @b fill_pattern(..) @/b: specifies the fill pattern. @/li
# @/ul
#
@@ -4355,6 +4357,7 @@ CODE
column_step = nil
pattern = nil
origin = RBA::DPoint::new
+ repeat = false
args.each_with_index do |a,ai|
if a.is_a?(DRCSource)
@@ -4381,6 +4384,7 @@ CODE
end
elsif a.is_a?(DRCFillOrigin)
origin = a.origin
+ repeat = a.repeat
else
raise("Argument ##{ai+1} not understood for '#{m}'")
end
@@ -4435,31 +4439,22 @@ CODE
tp.var("cs", cs)
tp.var("origin", origin)
tp.var("fc_index", fc_index)
+ tp.var("repeat", repeat)
+ tp.var("with_left", with_left)
- if with_left
- tp.queue(<<"END")
- var tc_box = _frame.bbox;
- var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
- !tile_box.empty && (
- tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height)));
- tile_box = tile_box & tc_box;
- var left = Region.new;
+ tp.queue(<<"END")
+ var tc_box = _frame.bbox;
+ var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
+ !tile_box.empty && (
+ tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height)));
+ tile_box = tile_box & tc_box;
+ var left = with_left ? Region.new : nil;
+ repeat ?
+ (region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, Vector.new, left, _tile.bbox) :
(region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, Vector.new, left, _tile.bbox);
- _output(#{result_arg}, left)
- )
+ with_left && _output(#{result_arg}, left)
+ )
END
- else
- tp.queue(<<"END")
- var tc_box = _frame.bbox;
- var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
- !tile_box.empty && (
- tile_box.right = tile_box.right + rs.x - 1;
- tile_box.top = tile_box.top + cs.y - 1;
- tile_box = tile_box & tc_box;
- (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, nil, Vector.new, nil, _tile.bbox)
- )
-END
- end
begin
@engine._output_layout.start_changes
@@ -4477,10 +4472,19 @@ END
end
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
- self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result)
+ if repeat
+ self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, RBA::Vector::new, result)
+ else
+ self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result)
+ end
end
end
+
+ if fill_cell.parent_cells == 0
+ # fill cell not required (not placed) -> remove
+ fill_cell.delete
+ end
self.data.disable_progress
diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb
index 283a7813d..0da810678 100644
--- a/src/drc/drc/built-in-macros/_drc_tags.rb
+++ b/src/drc/drc/built-in-macros/_drc_tags.rb
@@ -334,7 +334,8 @@ module DRC
# A wrapper for the fill origin definition
class DRCFillOrigin
- def initialize(x = nil, y = nil)
+ def initialize(x = nil, y = nil, repeat = false)
+ @repeat = repeat
if !x && !y
@origin = nil
else
@@ -350,6 +351,9 @@ module DRC
def origin
@origin
end
+ def repeat
+ @repeat
+ end
end
# A wrapper for the tile_size option
diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc
index 36b46732a..5d3abc750 100644
--- a/src/drc/unit_tests/drcSimpleTests.cc
+++ b/src/drc/unit_tests/drcSimpleTests.cc
@@ -1222,3 +1222,13 @@ TEST(45_fillWithOverlappingBoxesTiled)
{
run_test (_this, "45", false);
}
+
+TEST(46_fillWithOverlappingBoxes)
+{
+ run_test (_this, "46", false);
+}
+
+TEST(47_fillWithOverlappingBoxesTiled)
+{
+ run_test (_this, "47", false);
+}
diff --git a/src/edt/edt/edtInstPropertiesPage.cc b/src/edt/edt/edtInstPropertiesPage.cc
index 2360211db..4034061fe 100644
--- a/src/edt/edt/edtInstPropertiesPage.cc
+++ b/src/edt/edt/edtInstPropertiesPage.cc
@@ -542,6 +542,9 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
try {
tl::from_string (tl::to_string (rows_le->text ()), rows);
+ if (rows < 1) {
+ throw tl::Exception (tl::to_string (tr ("Rows count can't be zero")));
+ }
lay::indicate_error (rows_le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (rows_le, &ex);
@@ -550,6 +553,9 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
try {
tl::from_string (tl::to_string (columns_le->text ()), cols);
+ if (cols < 1) {
+ throw tl::Exception (tl::to_string (tr ("Columns count can't be zero")));
+ }
lay::indicate_error (columns_le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (columns_le, &ex);
diff --git a/src/lay/lay/doc/about/25d_screenshot.png b/src/lay/lay/doc/about/25d_screenshot.png
new file mode 100644
index 000000000..4515ae722
Binary files /dev/null and b/src/lay/lay/doc/about/25d_screenshot.png differ
diff --git a/src/lay/lay/doc/about/25d_view.xml b/src/lay/lay/doc/about/25d_view.xml
new file mode 100644
index 000000000..f112260b7
--- /dev/null
+++ b/src/lay/lay/doc/about/25d_view.xml
@@ -0,0 +1,147 @@
+
+
+
+
+
+ The 2.5d View
+
+
+
+
+
+
+
+
+ The "2.5d view" offers a semi-3d view of the layout. It's not a full 3d view as the layers are only extruded vertically
+ into layers with a certain thickness. The view cannot model process topology, but it can visualize
+ wiring congestions in a three-dimensional space or the vertical relative dimensions of features of the process stack.
+
+
+
+ To open the view, use "Tools/2.5d View". Currently, the performance is limited, a rough number for a
+ practical limit is around 100k polygons. The 2.5d view is only available, if KLayout was compiled with
+ OpenGL support.
+
+
+
+
+
+
+
Setup
+
+
+ The 2.5d view needs a technology setup explaining the way the layers are transformed into planes.
+ The setup is provided within a technology. Open the technology manager (File/Manage Technologies) and
+ navigate to the "Z Stack (2.5d)" component. The setup is basically a list of entries listing the
+ layer from which to take the shapes and the depth information.
+
+
+
+ Each entry is a single line. Empty lines are ignored. Everything after a '#' character is
+ considered a comment.
+
+
+
+ Each specification line consists of a layer specification, a colon and arguments.
+ The arguments are named (like "x=...") or in serial. Parameters are separated by comma or blanks.
+ Named arguments are:
+
+
+
+
zstart: The lower z position of the extruded layer in µm
+
zstop: The upper z position of the extruded layer in µm
+
height: The height of the extruded layer in µm
+
+
+
+ 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart',
+ the upper level of the previous layer will be used.
+
+
+
+ If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to
+ 'zstart' and 'zstop'.
+
+
+
+ Here are some examples:
+
+
+
1: 0.5 1.5 # extrude layer 1/0 from 0.5 to 1.5 vertically\n"
+1/0: 0.5 1.5 # same with explicit datatype\n"
+1: zstop=1.5, zstart=0.5 # same with named parameters\n"
+1: height=1.0, zstop=1.5 # same with z stop minus height\n"
+1: 1.0 zstop=1.5 # same with height as unnamed parameter\n"
+
+
+
Variables
+
+
+ You can declare variables inside the setup files and use them in formulas for
+ computed values. Variables are defined and set with the "var" keyword on a single line.
+ The notation follows the "expression" syntax used in many other places inside KLayout
+ ().
+
+ For more flexibility, but of little practical use for now, conditionals are provided.
+ "if", "else", "elsif" and "end" for as in other languages, e.g. Ruby:
+
+ The navigation is based on the movement of the camera while the scene is
+ formed by the extruded layout. The scene can be scaled to provide zoom features.
+ Scaling and rotation is relative to the pivot point which is indicated by the
+ compass icon on the ground plane.
+
+
+
+ This is a short list of the navigation controls which act on the camera:
+
+
+
+
Dragging with the right mouse button down: change azimuth and elevation angle
+
Dragging with the middle mouse button down: move the pivot up and down or left and right
+
Mouse wheel: moves the pivot forward and backward
+
Control key + mouse wheel: magnify or shrink the layout
+
Press and hold shift key: switch to top level view (see below)
+
Up/down keys: move the pivot forward or backward
+
Left/right keys: move the pivot to the left or the right
+
Control + up/down keys: change the elevation angle
+
Control + left/right keys: change the azimuth angle
+
+
+
+ In top level view, the navigation is slightly different:
+
+
+
+
Dragging with the right mouse button down: change azimuth angle
+
mouse wheel: magnify or shrink the layout
+
Up/down/left/right keys: move the pivot on the horizontal plane
+
+
+
+
diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml
index 0d2b34c84..4b9b0554c 100644
--- a/src/lay/lay/doc/about/drc_ref_layer.xml
+++ b/src/lay/lay/doc/about/drc_ref_layer.xml
@@ -1044,7 +1044,9 @@ a positive value. A horizontal displacement component can be specified too, whic
origin(x, y) : specifies a fixed point to align the pattern with. This point specifies the location
of the reference point for one pattern cell.
auto_origin : lets the algorithm choose the origin. This may result is a slightly better fill coverage
-as the algorithm is able to determine a pattern origin per fill island.
+as the algorithm is able to determine a pattern origin per island to fill.
+
multi_origin : lets the algorithm choose the origin and repeats the fill with different origins
+until no further fill cell can be fitted.