mirror of https://github.com/KLayout/klayout.git
Merge branch 'bugfixes' into issue-757
This commit is contained in:
commit
841e6c8726
279
Changelog
279
Changelog
|
|
@ -1,19 +1,276 @@
|
||||||
0.27 (2020-xx-xx):
|
|
||||||
|
|
||||||
* Enhancement: %GITHUB%/issues/521
|
0.27 (2021-04-xx):
|
||||||
Enhanced API for ObjectInstPath
|
|
||||||
|
* 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
|
* Enhancement: %GITHUB%/issues/558
|
||||||
Edges#extents, Texts#extents and EdgePairs#extents now
|
Edges#extents, Texts#extents and EdgePairs#extents now
|
||||||
work hierarchically in deep mode. In DRC, this means,
|
work hierarchically in deep mode. In DRC, this means,
|
||||||
"extents" is a deep-enabled method now.
|
"extents" is a deep-enabled method now.
|
||||||
* Enhancement: %GITHUB%/issues/563
|
* Enhancement: %GITHUB%/issues/535
|
||||||
True support for text objects in DRC/LVS (text layers)
|
Image handling enhancements.
|
||||||
* Enhancement: ability to utilize a LayoutView as a Widget
|
* Enhancement: %GITHUB%/issues/521
|
||||||
Standalone instantiation of a LayoutView object is
|
Enhanced API for ObjectInstPath.
|
||||||
supported now. So it becomes possible to create
|
* Enhancement: %GITHUB%/issues/487
|
||||||
custom MainWindow UIs and embed a layout view there.
|
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
|
* Bugfix: %GITHUB%/issues/539
|
||||||
An internal error happened on netlist flatten sometimes
|
An internal error happened on netlist flatten sometimes
|
||||||
|
|
@ -28,6 +285,8 @@
|
||||||
* Bugfix: %GITHUB%/issues/544
|
* Bugfix: %GITHUB%/issues/544
|
||||||
Duplicate .global statements in SPICE netlists created
|
Duplicate .global statements in SPICE netlists created
|
||||||
duplicate pins
|
duplicate pins
|
||||||
|
* Bugfix: %GITHUB%/issues/548
|
||||||
|
A shielding issue was fixed for DRC space measurements
|
||||||
* Bugfix: diff tool bug with paths
|
* Bugfix: diff tool bug with paths
|
||||||
Differences in path points where no reported
|
Differences in path points where no reported
|
||||||
* Enhancement: documentation clarifications and typos fixed
|
* Enhancement: documentation clarifications and typos fixed
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,6 @@ PropertiesPage::swap_points_clicked ()
|
||||||
y1->setText (ty1);
|
y1->setText (ty1);
|
||||||
y2->setText (ty2);
|
y2->setText (ty2);
|
||||||
|
|
||||||
db::Transaction t (manager (), tl::to_string (QObject::tr ("Swap ruler points")));
|
|
||||||
emit edited ();
|
emit edited ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,7 +223,6 @@ PropertiesPage::snap_to_layout_clicked ()
|
||||||
y2->setText (ys);
|
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 ();
|
emit edited ();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -249,7 +247,6 @@ PropertiesPage::snap_to_layout_clicked ()
|
||||||
x2->setText (tl::to_qstring (tl::micron_to_string (ee.second.x ())));
|
x2->setText (tl::to_qstring (tl::micron_to_string (ee.second.x ())));
|
||||||
y2->setText (tl::to_qstring (tl::micron_to_string (ee.second.y ())));
|
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 ();
|
emit edited ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1274,8 +1274,9 @@ Service::end_move (const db::DPoint &, lay::angle_constraint_type)
|
||||||
// compute moved object and replace
|
// compute moved object and replace
|
||||||
ant::Object *rnew = new ant::Object (*robj);
|
ant::Object *rnew = new ant::Object (*robj);
|
||||||
rnew->transform (m_trans);
|
rnew->transform (m_trans);
|
||||||
|
int new_id = rnew->id ();
|
||||||
mp_view->annotation_shapes ().replace (s->first, db::DUserObject (rnew));
|
mp_view->annotation_shapes ().replace (s->first, db::DUserObject (rnew));
|
||||||
annotation_changed_event (rnew->id ());
|
annotation_changed_event (new_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -760,6 +760,15 @@ public:
|
||||||
// .. nothing else ..
|
// .. 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
|
* @brief Assignment
|
||||||
*/
|
*/
|
||||||
|
|
@ -774,6 +783,21 @@ public:
|
||||||
return *this;
|
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
|
* @brief The destructor
|
||||||
*/
|
*/
|
||||||
|
|
@ -1729,6 +1753,15 @@ public:
|
||||||
// .. nothing else ..
|
// .. 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
|
* @brief Assignment
|
||||||
*/
|
*/
|
||||||
|
|
@ -1742,6 +1775,20 @@ public:
|
||||||
return *this;
|
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
|
* @brief The destructor
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -357,10 +357,7 @@ CompoundRegionMultiInputOperationNode::init ()
|
||||||
|
|
||||||
CompoundRegionMultiInputOperationNode::~CompoundRegionMultiInputOperationNode ()
|
CompoundRegionMultiInputOperationNode::~CompoundRegionMultiInputOperationNode ()
|
||||||
{
|
{
|
||||||
for (tl::shared_collection<CompoundRegionOperationNode>::iterator i = m_children.begin (); i != m_children.end (); ++i) {
|
// .. nothing yet ..
|
||||||
delete i.operator-> ();
|
|
||||||
}
|
|
||||||
m_children.clear ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
||||||
// provide some explanation for the initialization
|
// provide some explanation for the initialization
|
||||||
m_src =
|
m_src =
|
||||||
"# Provide z stack information here\n"
|
"# Provide z stack information here\n"
|
||||||
|
"#\n"
|
||||||
"# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\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"
|
"# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n"
|
||||||
"# Named arguments are:\n"
|
"# Named arguments are:\n"
|
||||||
|
|
@ -127,7 +128,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
||||||
"# zstop The upper z position of the extruded layer in µm\n"
|
"# zstop The upper z position of the extruded layer in µm\n"
|
||||||
"# height The height of the extruded layer in µm\n"
|
"# height The height of the extruded layer in µm\n"
|
||||||
"#\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"
|
"# the upper level of the previous layer will be used.\n"
|
||||||
"#\n"
|
"#\n"
|
||||||
"# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\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: 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: 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"
|
"# 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)
|
D25TechnologyComponent::D25TechnologyComponent (const D25TechnologyComponent &d)
|
||||||
: db::TechnologyComponent (d25_component_name (), d25_description ())
|
: db::TechnologyComponent (d25_component_name (), d25_description ())
|
||||||
{
|
{
|
||||||
m_layers = d.m_layers;
|
|
||||||
m_src = d.m_src;
|
m_src = d.m_src;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
D25TechnologyComponent::layers_type
|
||||||
D25TechnologyComponent::compile_from_source (const std::string &src)
|
D25TechnologyComponent::compile_from_source () const
|
||||||
{
|
{
|
||||||
|
layers_type layers;
|
||||||
|
|
||||||
int current_line = 0;
|
int current_line = 0;
|
||||||
m_layers.clear ();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
std::vector<std::string> lines = tl::split (src, "\n");
|
tl::Eval eval;
|
||||||
|
std::vector<bool> conditional_stack;
|
||||||
|
|
||||||
|
std::vector<std::string> lines = tl::split (m_src, "\n");
|
||||||
for (std::vector<std::string>::const_iterator l = lines.begin (); l != lines.end (); ++l) {
|
for (std::vector<std::string>::const_iterator l = lines.begin (); l != lines.end (); ++l) {
|
||||||
|
|
||||||
++current_line;
|
++current_line;
|
||||||
|
|
@ -168,12 +196,86 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
||||||
// ignore comments
|
// ignore comments
|
||||||
} else if (ex.at_end ()) {
|
} else if (ex.at_end ()) {
|
||||||
// ignore empty lines
|
// 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 {
|
} else {
|
||||||
|
|
||||||
db::D25LayerInfo info;
|
db::D25LayerInfo info;
|
||||||
if (! m_layers.empty ()) {
|
if (! layers.empty ()) {
|
||||||
info.set_zstart (m_layers.back ().zstop ());
|
info.set_zstart (layers.back ().zstop ());
|
||||||
info.set_zstop (m_layers.back ().zstop ());
|
info.set_zstop (layers.back ().zstop ());
|
||||||
}
|
}
|
||||||
|
|
||||||
tl::Variant z0, z1, h;
|
tl::Variant z0, z1, h;
|
||||||
|
|
@ -191,16 +293,18 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
double pv = 0.0;
|
tl::Expression pvx;
|
||||||
|
|
||||||
std::string pn;
|
std::string pn;
|
||||||
if (ex.try_read_name (pn)) {
|
if (ex.try_read_name (pn)) {
|
||||||
ex.expect ("=");
|
ex.expect ("=");
|
||||||
ex.read (pv);
|
eval.parse (pvx, ex);
|
||||||
} else {
|
} else {
|
||||||
ex.read (pv);
|
eval.parse (pvx, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double pv = pvx.execute ().to_double ();
|
||||||
|
|
||||||
ex.test (",");
|
ex.test (",");
|
||||||
|
|
||||||
if (pn.empty ()) {
|
if (pn.empty ()) {
|
||||||
|
|
@ -220,7 +324,7 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
||||||
if (args.size () == 0) {
|
if (args.size () == 0) {
|
||||||
if (z0.is_nil () && z1.is_nil ()) {
|
if (z0.is_nil () && z1.is_nil ()) {
|
||||||
if (! h.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 ()) {
|
} else if (z0.is_nil ()) {
|
||||||
info.set_zstop (z1.to_double ());
|
info.set_zstop (z1.to_double ());
|
||||||
|
|
@ -239,28 +343,28 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
||||||
} else if (args.size () == 1) {
|
} else if (args.size () == 1) {
|
||||||
if (! h.is_nil ()) {
|
if (! h.is_nil ()) {
|
||||||
if (! z0.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 ()) {
|
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_zstart (args[0]);
|
||||||
info.set_zstop (args[0] + h.to_double ());
|
info.set_zstop (args[0] + h.to_double ());
|
||||||
} else {
|
} else {
|
||||||
if (! z1.is_nil ()) {
|
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]);
|
info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]);
|
||||||
}
|
}
|
||||||
} else if (args.size () == 2) {
|
} else if (args.size () == 2) {
|
||||||
if (! z0.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 ()) {
|
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 ()) {
|
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_zstart (args[0]);
|
||||||
info.set_zstop (args[1]);
|
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)")));
|
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) {
|
} catch (tl::Exception &ex) {
|
||||||
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
|
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_src = src;
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
D25TechnologyComponent::to_string () const
|
D25TechnologyComponent::to_string () const
|
||||||
{
|
{
|
||||||
|
layers_type layers = compile_from_source ();
|
||||||
std::string res;
|
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 ()) {
|
if (! res.empty ()) {
|
||||||
res += "\n";
|
res += "\n";
|
||||||
}
|
}
|
||||||
|
|
@ -317,11 +426,6 @@ public:
|
||||||
virtual tl::XMLElementBase *xml_element () const
|
virtual tl::XMLElementBase *xml_element () const
|
||||||
{
|
{
|
||||||
return new db::TechnologyComponentXMLElement<D25TechnologyComponent> (d25_component_name (),
|
return new db::TechnologyComponentXMLElement<D25TechnologyComponent> (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")
|
tl::make_member (&D25TechnologyComponent::src, &D25TechnologyComponent::set_src, "src")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,55 +76,8 @@ public:
|
||||||
D25TechnologyComponent (const D25TechnologyComponent &d);
|
D25TechnologyComponent (const D25TechnologyComponent &d);
|
||||||
|
|
||||||
typedef std::list<D25LayerInfo> layers_type;
|
typedef std::list<D25LayerInfo> layers_type;
|
||||||
typedef layers_type::const_iterator const_iterator;
|
|
||||||
typedef layers_type::iterator iterator;
|
|
||||||
|
|
||||||
void compile_from_source (const std::string &src);
|
layers_type compile_from_source () const;
|
||||||
|
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &src () const
|
const std::string &src () const
|
||||||
{
|
{
|
||||||
|
|
@ -145,7 +98,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
layers_type m_layers;
|
|
||||||
std::string m_src;
|
std::string m_src;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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")));
|
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 ());
|
db::Vector kernel_origin (fc_bbox.left (), fc_bbox.bottom ());
|
||||||
|
|
||||||
std::vector <db::Polygon> filled_regions;
|
std::vector <db::Polygon> filled_regions;
|
||||||
|
|
@ -256,13 +251,21 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
continue;
|
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;
|
db::Point o = origin;
|
||||||
if (enhanced_fill) {
|
if (ef) {
|
||||||
o = fp->hull () [0];
|
o = fp->hull () [0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ninsts = 0;
|
||||||
|
|
||||||
GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ());
|
GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ());
|
||||||
|
|
||||||
for (unsigned int i = 0; i < am.area_maps (); ++i) {
|
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
|
DB_PUBLIC void
|
||||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
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::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;
|
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;
|
++iteration;
|
||||||
|
|
||||||
remaining.clear ();
|
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);
|
new_fill_region.swap (remaining);
|
||||||
fill_region = &new_fill_region;
|
fill_region = &new_fill_region;
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,6 @@ fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
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::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 ());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,14 @@ struct layer
|
||||||
operator= (d);
|
operator= (d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The move constructor
|
||||||
|
*/
|
||||||
|
layer (const layer &&d)
|
||||||
|
{
|
||||||
|
operator= (d);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The assignment operator
|
* @brief The assignment operator
|
||||||
*
|
*
|
||||||
|
|
@ -123,6 +131,20 @@ struct layer
|
||||||
return *this;
|
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
|
* @brief Get the iterator for an object given by a pointer
|
||||||
*/
|
*/
|
||||||
|
|
@ -207,6 +229,18 @@ struct layer
|
||||||
return m_box_tree.insert (sh);
|
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
|
* @brief Replace the given element with a new one
|
||||||
*
|
*
|
||||||
|
|
@ -228,6 +262,19 @@ struct layer
|
||||||
return *ncpos;
|
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
|
* @brief Erasing of an element
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1626,7 +1626,7 @@ AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, const db::Vecto
|
||||||
m_ny = ny;
|
m_ny = ny;
|
||||||
|
|
||||||
if (mp_av) {
|
if (mp_av) {
|
||||||
delete mp_av;
|
delete[] mp_av;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_av = new area_type [nx * ny];
|
mp_av = new area_type [nx * ny];
|
||||||
|
|
|
||||||
|
|
@ -558,7 +558,7 @@ public:
|
||||||
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
||||||
|
|
||||||
virtual const TransformationReducer *vars () const { return 0; }
|
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 requires_raw_input () const { return false; }
|
||||||
virtual bool wants_variants () const { return true; }
|
virtual bool wants_variants () const { return true; }
|
||||||
virtual bool result_must_not_be_merged () const { return false; }
|
virtual bool result_must_not_be_merged () const { return false; }
|
||||||
|
|
@ -577,7 +577,7 @@ public:
|
||||||
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
||||||
|
|
||||||
virtual const TransformationReducer *vars () const { return 0; }
|
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 requires_raw_input () const { return false; }
|
||||||
virtual bool wants_variants () const { return true; }
|
virtual bool wants_variants () const { return true; }
|
||||||
virtual bool result_must_not_be_merged () const { return false; }
|
virtual bool result_must_not_be_merged () const { return false; }
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,18 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The move constructor
|
||||||
|
*/
|
||||||
|
user_object (user_object<C> &&d)
|
||||||
|
: mp_obj (0)
|
||||||
|
{
|
||||||
|
if (d.mp_obj) {
|
||||||
|
set_ptr (d.mp_obj);
|
||||||
|
d.mp_obj = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assignment operator
|
* @brief Assignment operator
|
||||||
*/
|
*/
|
||||||
|
|
@ -219,6 +231,20 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assignment operator (move)
|
||||||
|
*/
|
||||||
|
user_object<C> &operator= (user_object<C> &&d)
|
||||||
|
{
|
||||||
|
if (d.mp_obj) {
|
||||||
|
set_ptr (d.mp_obj);
|
||||||
|
d.mp_obj = 0;
|
||||||
|
} else {
|
||||||
|
set_ptr (0);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor
|
* @brief The destructor
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1312,9 +1312,9 @@ fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill
|
||||||
|
|
||||||
static void
|
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,
|
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)
|
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
|
||||||
|
|
@ -1881,7 +1881,6 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
gsi::arg ("column_step"),
|
gsi::arg ("column_step"),
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("origin", db::Point ()),
|
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
"@brief Fills the given region with cells of the given type in enhanced mode with iterations\n"
|
"@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. "
|
"This version operates like \\fill_region, but repeats the fill generation until no further fill cells can be placed. "
|
||||||
|
|
|
||||||
|
|
@ -730,9 +730,9 @@ fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill
|
||||||
|
|
||||||
static void
|
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,
|
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;
|
static db::Point default_origin;
|
||||||
|
|
@ -2921,7 +2921,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||||
gsi::arg ("column_step"),
|
gsi::arg ("column_step"),
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("origin", db::Point ()),
|
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ void run_test1 (tl::TestBase *_this, bool deep)
|
||||||
unsigned int l1002 = ly.get_layer (db::LayerProperties (1002, 0));
|
unsigned int l1002 = ly.get_layer (db::LayerProperties (1002, 0));
|
||||||
res.insert_into (&ly, *ly.begin_top_down (), l1002);
|
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);
|
db::CompoundRegionCheckOperationNode space_check (primary, db::SpaceRelation, false /*==all polygons*/, 1050, check_options);
|
||||||
|
|
||||||
res = r.cop_to_edge_pairs (space_check);
|
res = r.cop_to_edge_pairs (space_check);
|
||||||
|
|
|
||||||
|
|
@ -30,44 +30,73 @@ TEST(1)
|
||||||
{
|
{
|
||||||
db::D25TechnologyComponent comp;
|
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");
|
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");
|
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");
|
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");
|
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");
|
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");
|
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");
|
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 {
|
try {
|
||||||
comp.compile_from_source ("blabla");
|
comp.set_src ("blabla");
|
||||||
|
comp.compile_from_source ();
|
||||||
EXPECT_EQ (false, true);
|
EXPECT_EQ (false, true);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
||||||
try {
|
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);
|
EXPECT_EQ (false, true);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
||||||
try {
|
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);
|
EXPECT_EQ (false, true);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
||||||
try {
|
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);
|
EXPECT_EQ (false, true);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -694,8 +694,8 @@ TEST(10_HullsAndHoles)
|
||||||
|
|
||||||
db::Region hulls = r1_sized.hulls ();
|
db::Region hulls = r1_sized.hulls ();
|
||||||
db::Region holes = r1_sized.holes ();
|
db::Region holes = r1_sized.holes ();
|
||||||
EXPECT_EQ (hulls.is_merged (), true);
|
EXPECT_EQ (hulls.is_merged (), false);
|
||||||
EXPECT_EQ (holes.is_merged (), true);
|
EXPECT_EQ (holes.is_merged (), false);
|
||||||
|
|
||||||
db::Layout target;
|
db::Layout target;
|
||||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,10 @@ module DRC
|
||||||
DRCFillOrigin::new
|
DRCFillOrigin::new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def multi_origin
|
||||||
|
DRCFillOrigin::new(nil, nil, true)
|
||||||
|
end
|
||||||
|
|
||||||
def origin(x, y)
|
def origin(x, y)
|
||||||
DRCFillOrigin::new(x, y)
|
DRCFillOrigin::new(x, y)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -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
|
# @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
|
# 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
|
# @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
|
# @li @b fill_pattern(..) @/b: specifies the fill pattern. @/li
|
||||||
# @/ul
|
# @/ul
|
||||||
#
|
#
|
||||||
|
|
@ -4355,6 +4357,7 @@ CODE
|
||||||
column_step = nil
|
column_step = nil
|
||||||
pattern = nil
|
pattern = nil
|
||||||
origin = RBA::DPoint::new
|
origin = RBA::DPoint::new
|
||||||
|
repeat = false
|
||||||
|
|
||||||
args.each_with_index do |a,ai|
|
args.each_with_index do |a,ai|
|
||||||
if a.is_a?(DRCSource)
|
if a.is_a?(DRCSource)
|
||||||
|
|
@ -4381,6 +4384,7 @@ CODE
|
||||||
end
|
end
|
||||||
elsif a.is_a?(DRCFillOrigin)
|
elsif a.is_a?(DRCFillOrigin)
|
||||||
origin = a.origin
|
origin = a.origin
|
||||||
|
repeat = a.repeat
|
||||||
else
|
else
|
||||||
raise("Argument ##{ai+1} not understood for '#{m}'")
|
raise("Argument ##{ai+1} not understood for '#{m}'")
|
||||||
end
|
end
|
||||||
|
|
@ -4435,31 +4439,22 @@ CODE
|
||||||
tp.var("cs", cs)
|
tp.var("cs", cs)
|
||||||
tp.var("origin", origin)
|
tp.var("origin", origin)
|
||||||
tp.var("fc_index", fc_index)
|
tp.var("fc_index", fc_index)
|
||||||
|
tp.var("repeat", repeat)
|
||||||
|
tp.var("with_left", with_left)
|
||||||
|
|
||||||
if with_left
|
tp.queue(<<"END")
|
||||||
tp.queue(<<"END")
|
var tc_box = _frame.bbox;
|
||||||
var tc_box = _frame.bbox;
|
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
||||||
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
!tile_box.empty && (
|
||||||
!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.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height)));
|
tile_box = tile_box & tc_box;
|
||||||
tile_box = tile_box & tc_box;
|
var left = with_left ? Region.new : nil;
|
||||||
var left = Region.new;
|
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);
|
(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
|
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
|
begin
|
||||||
@engine._output_layout.start_changes
|
@engine._output_layout.start_changes
|
||||||
|
|
@ -4477,10 +4472,19 @@ END
|
||||||
end
|
end
|
||||||
|
|
||||||
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
|
@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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if fill_cell.parent_cells == 0
|
||||||
|
# fill cell not required (not placed) -> remove
|
||||||
|
fill_cell.delete
|
||||||
|
end
|
||||||
|
|
||||||
self.data.disable_progress
|
self.data.disable_progress
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,8 @@ module DRC
|
||||||
|
|
||||||
# A wrapper for the fill origin definition
|
# A wrapper for the fill origin definition
|
||||||
class DRCFillOrigin
|
class DRCFillOrigin
|
||||||
def initialize(x = nil, y = nil)
|
def initialize(x = nil, y = nil, repeat = false)
|
||||||
|
@repeat = repeat
|
||||||
if !x && !y
|
if !x && !y
|
||||||
@origin = nil
|
@origin = nil
|
||||||
else
|
else
|
||||||
|
|
@ -350,6 +351,9 @@ module DRC
|
||||||
def origin
|
def origin
|
||||||
@origin
|
@origin
|
||||||
end
|
end
|
||||||
|
def repeat
|
||||||
|
@repeat
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# A wrapper for the tile_size option
|
# A wrapper for the tile_size option
|
||||||
|
|
|
||||||
|
|
@ -1222,3 +1222,13 @@ TEST(45_fillWithOverlappingBoxesTiled)
|
||||||
{
|
{
|
||||||
run_test (_this, "45", false);
|
run_test (_this, "45", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(46_fillWithOverlappingBoxes)
|
||||||
|
{
|
||||||
|
run_test (_this, "46", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(47_fillWithOverlappingBoxesTiled)
|
||||||
|
{
|
||||||
|
run_test (_this, "47", false);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -542,6 +542,9 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tl::from_string (tl::to_string (rows_le->text ()), rows);
|
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);
|
lay::indicate_error (rows_le, (tl::Exception *) 0);
|
||||||
} catch (tl::Exception &ex) {
|
} catch (tl::Exception &ex) {
|
||||||
lay::indicate_error (rows_le, &ex);
|
lay::indicate_error (rows_le, &ex);
|
||||||
|
|
@ -550,6 +553,9 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tl::from_string (tl::to_string (columns_le->text ()), cols);
|
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);
|
lay::indicate_error (columns_le, (tl::Exception *) 0);
|
||||||
} catch (tl::Exception &ex) {
|
} catch (tl::Exception &ex) {
|
||||||
lay::indicate_error (columns_le, &ex);
|
lay::indicate_error (columns_le, &ex);
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
|
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||||
|
|
||||||
|
<doc>
|
||||||
|
|
||||||
|
<title>The 2.5d View</title>
|
||||||
|
<keyword name="2.5d"/>
|
||||||
|
<keyword name="3d"/>
|
||||||
|
<keyword name="2.5d View"/>
|
||||||
|
<keyword name="z-Stack"/>
|
||||||
|
|
||||||
|
<h2-index/>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img src="/about/25d_screenshot.png"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Setup</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Each entry is a single line. Empty lines are ignored. Everything after a '#' character is
|
||||||
|
considered a comment.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> <b>zstart</b>: The lower z position of the extruded layer in µm </li>
|
||||||
|
<li> <b>zstop</b>: The upper z position of the extruded layer in µm </li>
|
||||||
|
<li> <b>height</b>: The height of the extruded layer in µm </li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
'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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to
|
||||||
|
'zstart' and 'zstop'.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here are some examples:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>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"
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h4>Variables</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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
|
||||||
|
(<link href="/about/expressions.xml"/>).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here is an example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>var hmetal = 0.48\n"
|
||||||
|
7/0: 0.5 0.5+hmetal*2 # 2x thick metal\n"
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h4>Conditionals</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>var thick_m1 = true
|
||||||
|
if thickm1
|
||||||
|
1: 0.5 1.5
|
||||||
|
else
|
||||||
|
1: 0.5 1.2
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Navigating the 2.5d View</h2>
|
||||||
|
<keyword>navigation</keyword>
|
||||||
|
<keyword>2.5d navigation</keyword>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This is a short list of the navigation controls which act on the camera:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> Dragging with the right mouse button down: change azimuth and elevation angle </li>
|
||||||
|
<li> Dragging with the middle mouse button down: move the pivot up and down or left and right </li>
|
||||||
|
<li> Mouse wheel: moves the pivot forward and backward </li>
|
||||||
|
<li> Control key + mouse wheel: magnify or shrink the layout </li>
|
||||||
|
<li> Press and hold shift key: switch to top level view (see below) </li>
|
||||||
|
<li> Up/down keys: move the pivot forward or backward </li>
|
||||||
|
<li> Left/right keys: move the pivot to the left or the right </li>
|
||||||
|
<li> Control + up/down keys: change the elevation angle </li>
|
||||||
|
<li> Control + left/right keys: change the azimuth angle </li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In top level view, the navigation is slightly different:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> Dragging with the right mouse button down: change azimuth angle </li>
|
||||||
|
<li> mouse wheel: magnify or shrink the layout </li>
|
||||||
|
<li> Up/down/left/right keys: move the pivot on the horizontal plane </li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</doc>
|
||||||
|
|
||||||
|
|
@ -1044,7 +1044,9 @@ a positive value. A horizontal displacement component can be specified too, whic
|
||||||
<li><b>origin(x, y) </b>: specifies a fixed point to align the pattern with. This point specifies the location
|
<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>
|
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
|
<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>
|
<li><b>fill_pattern(..) </b>: specifies the fill pattern. </li>
|
||||||
</ul>
|
</ul>
|
||||||
</p><p>
|
</p><p>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
<topic href="/about/variant_notation.xml"/>
|
<topic href="/about/variant_notation.xml"/>
|
||||||
<topic href="/about/lef_def_import.xml"/>
|
<topic href="/about/lef_def_import.xml"/>
|
||||||
<topic href="/about/connectivity.xml"/>
|
<topic href="/about/connectivity.xml"/>
|
||||||
|
<topic href="/about/25d_view.xml"/>
|
||||||
<topic href="/about/symbolic_layers.xml"/>
|
<topic href="/about/symbolic_layers.xml"/>
|
||||||
<topic href="/about/layer_sources.xml"/>
|
<topic href="/about/layer_sources.xml"/>
|
||||||
<topic href="/about/macro_editor.xml"/>
|
<topic href="/about/macro_editor.xml"/>
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@
|
||||||
<file alias="lvs_ref_global.xml">doc/about/lvs_ref_global.xml</file>
|
<file alias="lvs_ref_global.xml">doc/about/lvs_ref_global.xml</file>
|
||||||
<file alias="lvs_ref_netter.xml">doc/about/lvs_ref_netter.xml</file>
|
<file alias="lvs_ref_netter.xml">doc/about/lvs_ref_netter.xml</file>
|
||||||
<file alias="packages.xml">doc/about/packages.xml</file>
|
<file alias="packages.xml">doc/about/packages.xml</file>
|
||||||
|
<file alias="25d_view.xml">doc/about/25d_view.xml</file>
|
||||||
|
<file alias="25d_screenshot.png">doc/about/25d_screenshot.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/help/manual">
|
<qresource prefix="/help/manual">
|
||||||
<file alias="adjust_origin.xml">doc/manual/adjust_origin.xml</file>
|
<file alias="adjust_origin.xml">doc/manual/adjust_origin.xml</file>
|
||||||
|
|
|
||||||
|
|
@ -3942,7 +3942,7 @@ MainWindow::menu_activated (const std::string &symbol)
|
||||||
if (current_view ()) {
|
if (current_view ()) {
|
||||||
current_view ()->menu_activated (symbol);
|
current_view ()->menu_activated (symbol);
|
||||||
} else {
|
} else {
|
||||||
throw tl::Exception (tl::to_string (QObject::tr ("No view is active")));
|
throw tl::Exception (tl::to_string (QObject::tr ("This function needs a layout but none was available")));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,12 @@
|
||||||
<family>Monospace</family>
|
<family>Monospace</family>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="lineWrapMode">
|
||||||
|
<enum>QTextEdit::NoWrap</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptRichText">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,12 @@ AnnotationShapes::AnnotationShapes (const AnnotationShapes &d)
|
||||||
operator= (d);
|
operator= (d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnnotationShapes::AnnotationShapes (const AnnotationShapes &&d)
|
||||||
|
: db::LayoutStateModel (true /*busy*/), db::Object (d)
|
||||||
|
{
|
||||||
|
operator= (d);
|
||||||
|
}
|
||||||
|
|
||||||
AnnotationShapes::~AnnotationShapes ()
|
AnnotationShapes::~AnnotationShapes ()
|
||||||
{
|
{
|
||||||
clear ();
|
clear ();
|
||||||
|
|
@ -106,7 +112,21 @@ AnnotationShapes::operator= (const AnnotationShapes &d)
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void
|
|
||||||
|
AnnotationShapes &
|
||||||
|
AnnotationShapes::operator= (const AnnotationShapes &&d)
|
||||||
|
{
|
||||||
|
if (&d != this) {
|
||||||
|
clear ();
|
||||||
|
if (manager () && manager ()->transacting ()) {
|
||||||
|
manager ()->queue (this, new AnnotationLayerOp (true /*insert*/, d.m_layer.begin (), d.m_layer.end ()));
|
||||||
|
}
|
||||||
|
m_layer = d.m_layer;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
AnnotationShapes::clear ()
|
AnnotationShapes::clear ()
|
||||||
{
|
{
|
||||||
if (manager () && manager ()->transacting ()) {
|
if (manager () && manager ()->transacting ()) {
|
||||||
|
|
@ -126,7 +146,17 @@ AnnotationShapes::insert (const shape_type &sh)
|
||||||
return *m_layer.insert (sh);
|
return *m_layer.insert (sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
const AnnotationShapes::shape_type &
|
||||||
|
AnnotationShapes::insert (const shape_type &&sh)
|
||||||
|
{
|
||||||
|
if (manager () && manager ()->transacting ()) {
|
||||||
|
manager ()->queue (this, new AnnotationLayerOp (true /*insert*/, sh));
|
||||||
|
}
|
||||||
|
invalidate_state (); // HINT: must come before the change is done!
|
||||||
|
return *m_layer.insert (sh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
AnnotationShapes::reserve (size_t n)
|
AnnotationShapes::reserve (size_t n)
|
||||||
{
|
{
|
||||||
m_layer.reserve (n);
|
m_layer.reserve (n);
|
||||||
|
|
@ -156,7 +186,21 @@ AnnotationShapes::replace (iterator pos, const shape_type &sh)
|
||||||
return *pos;
|
return *pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
const AnnotationShapes::shape_type &
|
||||||
|
AnnotationShapes::replace (iterator pos, const shape_type &&sh)
|
||||||
|
{
|
||||||
|
if (&*pos != &sh && *pos != sh) {
|
||||||
|
if (manager () && manager ()->transacting ()) {
|
||||||
|
manager ()->queue (this, new AnnotationLayerOp (false /*not insert*/, *pos));
|
||||||
|
manager ()->queue (this, new AnnotationLayerOp (true /*insert*/, sh));
|
||||||
|
}
|
||||||
|
invalidate_state (); // HINT: must come before the change is done!
|
||||||
|
m_layer.replace (pos, sh);
|
||||||
|
}
|
||||||
|
return *pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
AnnotationShapes::redo (db::Op *op)
|
AnnotationShapes::redo (db::Op *op)
|
||||||
{
|
{
|
||||||
AnnotationLayerOp *layop = dynamic_cast<AnnotationLayerOp *> (op);
|
AnnotationLayerOp *layop = dynamic_cast<AnnotationLayerOp *> (op);
|
||||||
|
|
|
||||||
|
|
@ -135,16 +135,37 @@ public:
|
||||||
*/
|
*/
|
||||||
AnnotationShapes (const AnnotationShapes &d);
|
AnnotationShapes (const AnnotationShapes &d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy ctor
|
||||||
|
*/
|
||||||
|
AnnotationShapes (const AnnotationShapes &&d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assignment operator
|
* @brief Assignment operator
|
||||||
*/
|
*/
|
||||||
AnnotationShapes &operator= (const AnnotationShapes &d);
|
AnnotationShapes &operator= (const AnnotationShapes &d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assignment operator (move)
|
||||||
|
*/
|
||||||
|
AnnotationShapes &operator= (const AnnotationShapes &&d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Insert a shape_type
|
* @brief Insert a shape_type
|
||||||
*/
|
*/
|
||||||
const shape_type &insert (const shape_type &sh);
|
const shape_type &insert (const shape_type &sh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Insert a sequence of DUserObject shapes
|
||||||
|
*
|
||||||
|
* Inserts a sequence of shapes [from,to)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Insert a shape_type (move semantics)
|
||||||
|
*/
|
||||||
|
const shape_type &insert (const shape_type &&sh);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Insert a sequence of DUserObject shapes
|
* @brief Insert a sequence of DUserObject shapes
|
||||||
*
|
*
|
||||||
|
|
@ -212,6 +233,11 @@ public:
|
||||||
*/
|
*/
|
||||||
const shape_type &replace (iterator pos, const shape_type &sh);
|
const shape_type &replace (iterator pos, const shape_type &sh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Replace an element at the given position with another shape (move semantics)
|
||||||
|
*/
|
||||||
|
const shape_type &replace (iterator pos, const shape_type &&sh);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief updates the bbox
|
* @brief updates the bbox
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ BookmarkItem::to_string () const
|
||||||
BrowserPanel::BrowserPanel (QWidget *parent)
|
BrowserPanel::BrowserPanel (QWidget *parent)
|
||||||
: QWidget (parent),
|
: QWidget (parent),
|
||||||
m_back_dm (this, &BrowserPanel::back),
|
m_back_dm (this, &BrowserPanel::back),
|
||||||
|
m_new_url_dm (this, &BrowserPanel::new_url),
|
||||||
mp_dispatcher (0)
|
mp_dispatcher (0)
|
||||||
{
|
{
|
||||||
init ();
|
init ();
|
||||||
|
|
@ -125,6 +126,7 @@ BrowserPanel::init ()
|
||||||
|
|
||||||
mp_ui->browser->addAction (mp_ui->action_find);
|
mp_ui->browser->addAction (mp_ui->action_find);
|
||||||
mp_ui->browser->addAction (mp_ui->action_bookmark);
|
mp_ui->browser->addAction (mp_ui->action_bookmark);
|
||||||
|
mp_ui->browser->setOpenLinks (false);
|
||||||
|
|
||||||
mp_ui->browser_bookmark_view->addAction (mp_ui->action_delete_bookmark);
|
mp_ui->browser_bookmark_view->addAction (mp_ui->action_delete_bookmark);
|
||||||
mp_ui->browser_bookmark_view->setContextMenuPolicy (Qt::ActionsContextMenu);
|
mp_ui->browser_bookmark_view->setContextMenuPolicy (Qt::ActionsContextMenu);
|
||||||
|
|
@ -138,7 +140,8 @@ BrowserPanel::init ()
|
||||||
connect (mp_ui->search_edit, SIGNAL (textEdited (const QString &)), this, SLOT (search_text_changed (const QString &)));
|
connect (mp_ui->search_edit, SIGNAL (textEdited (const QString &)), this, SLOT (search_text_changed (const QString &)));
|
||||||
connect (mp_ui->search_edit, SIGNAL (returnPressed ()), this, SLOT (search_edited ()));
|
connect (mp_ui->search_edit, SIGNAL (returnPressed ()), this, SLOT (search_edited ()));
|
||||||
connect (mp_ui->search_button, SIGNAL (clicked ()), this, SLOT (search_edited ()));
|
connect (mp_ui->search_button, SIGNAL (clicked ()), this, SLOT (search_edited ()));
|
||||||
connect (mp_ui->browser, SIGNAL (textChanged ()), this, SLOT (text_changed ()));
|
connect (mp_ui->browser, SIGNAL (sourceChanged (const QUrl &)), this, SLOT (source_changed ()));
|
||||||
|
connect (mp_ui->browser, SIGNAL (anchorClicked (const QUrl &)), this, SLOT (anchor_clicked (const QUrl &)));
|
||||||
connect (mp_ui->browser, SIGNAL (backwardAvailable (bool)), mp_ui->back_pb, SLOT (setEnabled (bool)));
|
connect (mp_ui->browser, SIGNAL (backwardAvailable (bool)), mp_ui->back_pb, SLOT (setEnabled (bool)));
|
||||||
connect (mp_ui->browser, SIGNAL (forwardAvailable (bool)), mp_ui->forward_pb, SLOT (setEnabled (bool)));
|
connect (mp_ui->browser, SIGNAL (forwardAvailable (bool)), mp_ui->forward_pb, SLOT (setEnabled (bool)));
|
||||||
connect (mp_ui->outline_tree, SIGNAL (itemActivated (QTreeWidgetItem *, int)), this, SLOT (outline_item_clicked (QTreeWidgetItem *)));
|
connect (mp_ui->outline_tree, SIGNAL (itemActivated (QTreeWidgetItem *, int)), this, SLOT (outline_item_clicked (QTreeWidgetItem *)));
|
||||||
|
|
@ -218,7 +221,7 @@ BrowserPanel::title () const
|
||||||
std::string
|
std::string
|
||||||
BrowserPanel::url () const
|
BrowserPanel::url () const
|
||||||
{
|
{
|
||||||
return m_cached_url;
|
return tl::to_string (mp_ui->browser->source ().toString ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -416,13 +419,24 @@ BrowserPanel::search_text_changed (const QString &text)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BrowserPanel::text_changed ()
|
BrowserPanel::source_changed ()
|
||||||
|
{
|
||||||
|
m_new_url_dm ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BrowserPanel::anchor_clicked (const QUrl &url)
|
||||||
|
{
|
||||||
|
mp_ui->browser->setSource (url);
|
||||||
|
source_changed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BrowserPanel::new_url ()
|
||||||
{
|
{
|
||||||
QString title = mp_ui->browser->document ()->metaInformation (QTextDocument::DocumentTitle);
|
QString title = mp_ui->browser->document ()->metaInformation (QTextDocument::DocumentTitle);
|
||||||
if (title != m_current_title) {
|
m_current_title = title;
|
||||||
m_current_title = title;
|
emit title_changed (title);
|
||||||
emit title_changed (title);
|
|
||||||
}
|
|
||||||
|
|
||||||
// refresh on-page search
|
// refresh on-page search
|
||||||
page_search_edited ();
|
page_search_edited ();
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,9 @@ protected slots:
|
||||||
void page_search_next();
|
void page_search_next();
|
||||||
void search_text_changed(const QString &text);
|
void search_text_changed(const QString &text);
|
||||||
void search_edited ();
|
void search_edited ();
|
||||||
void text_changed ();
|
void source_changed ();
|
||||||
|
void anchor_clicked (const QUrl &url);
|
||||||
|
void new_url ();
|
||||||
void outline_item_clicked (QTreeWidgetItem *item);
|
void outline_item_clicked (QTreeWidgetItem *item);
|
||||||
void bookmark_item_selected (QTreeWidgetItem *item);
|
void bookmark_item_selected (QTreeWidgetItem *item);
|
||||||
void delete_bookmark ();
|
void delete_bookmark ();
|
||||||
|
|
@ -462,6 +464,7 @@ private:
|
||||||
Ui::BrowserPanel *mp_ui;
|
Ui::BrowserPanel *mp_ui;
|
||||||
bool m_schedule_back;
|
bool m_schedule_back;
|
||||||
tl::DeferredMethod<BrowserPanel> m_back_dm;
|
tl::DeferredMethod<BrowserPanel> m_back_dm;
|
||||||
|
tl::DeferredMethod<BrowserPanel> m_new_url_dm;
|
||||||
std::string m_search_url, m_search_query_item;
|
std::string m_search_url, m_search_query_item;
|
||||||
QString m_current_title;
|
QString m_current_title;
|
||||||
QList<QTextEdit::ExtraSelection> m_search_selection;
|
QList<QTextEdit::ExtraSelection> m_search_selection;
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,13 @@ D25TechnologyComponentEditor::commit ()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string src = tl::to_string (src_te->toPlainText ());
|
std::string src = tl::to_string (src_te->toPlainText ());
|
||||||
data->compile_from_source (src);
|
|
||||||
|
// test-compile before setting it
|
||||||
|
db::D25TechnologyComponent tc;
|
||||||
|
tc.set_src (src);
|
||||||
|
tc.compile_from_source ();
|
||||||
|
|
||||||
|
data->set_src (src);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -1027,6 +1027,8 @@ NetlistBrowserPage::adjust_view ()
|
||||||
ebox += bbox_for_device_abstract (layout, a->device_abstract, a->trans);
|
ebox += bbox_for_device_abstract (layout, a->device_abstract, a->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trans *= device->trans ();
|
||||||
|
|
||||||
} else if (net) {
|
} else if (net) {
|
||||||
|
|
||||||
db::cell_index_type cell_index = net->circuit ()->cell_index ();
|
db::cell_index_type cell_index = net->circuit ()->cell_index ();
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ PropertiesDialog::apply ()
|
||||||
{
|
{
|
||||||
BEGIN_PROTECTED
|
BEGIN_PROTECTED
|
||||||
|
|
||||||
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Auto-apply changes")), m_transaction_id);
|
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,35 @@
|
||||||
|
|
||||||
<highlighting>
|
<highlighting>
|
||||||
|
|
||||||
|
<list name="Control Keywords">
|
||||||
|
<item> zstart </item>
|
||||||
|
<item> zstop </item>
|
||||||
|
<item> height </item>
|
||||||
|
</list>
|
||||||
|
|
||||||
|
<list name="Expression Keywords">
|
||||||
|
<item> true </item>
|
||||||
|
<item> false </item>
|
||||||
|
<item> nil </item>
|
||||||
|
</list>
|
||||||
|
|
||||||
<contexts>
|
<contexts>
|
||||||
|
|
||||||
<context name="Normal" attribute="Normal Text">
|
<context name="Normal" attribute="Normal Text" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
|
||||||
|
|
||||||
|
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||||
|
|
||||||
|
<StringDetect attribute="Symbol" String="var" context="Expect Assignment"/>
|
||||||
|
<StringDetect attribute="Symbol" String="print" context="Expression"/>
|
||||||
|
<StringDetect attribute="Symbol" String="error" context="Expression"/>
|
||||||
|
<StringDetect attribute="Symbol" String="if" context="Expression"/>
|
||||||
|
<StringDetect attribute="Symbol" String="elsif" context="Expression"/>
|
||||||
|
<StringDetect attribute="Symbol" String="else" context="Expect Lineend"/>
|
||||||
|
<StringDetect attribute="Symbol" String="end" context="Expect Lineend"/>
|
||||||
|
|
||||||
<DetectChar attribute="String" char=""" context="Quoted String"/>
|
<DetectChar attribute="String" char=""" context="Quoted String"/>
|
||||||
|
<DetectChar attribute="String" char="'" context="Apostrophed String"/>
|
||||||
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||||
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
|
|
||||||
|
|
||||||
<RegExpr attribute="Normal" String=":" context="After LD"/>
|
<RegExpr attribute="Normal" String=":" context="After LD"/>
|
||||||
|
|
||||||
|
|
@ -22,22 +44,52 @@
|
||||||
<DetectChar attribute="Normal" char="/" context="#stay"/>
|
<DetectChar attribute="Normal" char="/" context="#stay"/>
|
||||||
<RegExpr attribute="Raw String" String="[_a-zA-Z]\w*" context="#stay"/>
|
<RegExpr attribute="Raw String" String="[_a-zA-Z]\w*" context="#stay"/>
|
||||||
|
|
||||||
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
|
|
||||||
|
|
||||||
</context>
|
</context>
|
||||||
|
|
||||||
<context name="Comment" attribute="Comment" lineEndContext="Normal">
|
<context name="Comment" attribute="Comment" lineEndContext="Normal">
|
||||||
</context>
|
</context>
|
||||||
|
|
||||||
<context name="After LD" attribute="Normal" lineEndContext="Normal">
|
<context name="Expect Lineend" attribute="Normal" lineEndContext="Normal" fallthrough="true" fallthroughContext="Error">
|
||||||
|
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||||
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<context name="Expression" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
|
||||||
|
|
||||||
|
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||||
|
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||||
|
|
||||||
|
<keyword attribute="Symbol" String="Expression Keywords" context="#stay"/>
|
||||||
|
<keyword attribute="Symbol" String="Control Keywords" context="Expect Expression"/>
|
||||||
|
|
||||||
|
<DetectChar attribute="String" char=""" context="Quoted String"/>
|
||||||
|
<DetectChar attribute="String" char="'" context="Apostrophed String"/>
|
||||||
|
<RegExpr attribute="Name" String="[_a-zA-Z]\w*" context="#stay"/>
|
||||||
<RegExpr attribute="Float" String="\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="#stay"/>
|
<RegExpr attribute="Float" String="\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="#stay"/>
|
||||||
|
|
||||||
<DetectChar attribute="Normal" char="," context="#stay"/>
|
<DetectChar attribute="Normal" char="," context="#stay"/>
|
||||||
<DetectChar attribute="Normal" char="=" context="#stay"/>
|
<DetectChar attribute="Normal" char="(" context="#stay"/>
|
||||||
<StringDetect attribute="Symbol" String="zstart" context="#stay"/>
|
<DetectChar attribute="Normal" char=")" context="#stay"/>
|
||||||
<StringDetect attribute="Symbol" String="zstop" context="#stay"/>
|
<DetectChar attribute="Normal" char="[" context="#stay"/>
|
||||||
<StringDetect attribute="Symbol" String="height" context="#stay"/>
|
<DetectChar attribute="Normal" char="]" context="#stay"/>
|
||||||
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
|
|
||||||
|
<RegExpr attribute="Normal" String="[\^\*\.\+\-%/!=<>&|,\?:]" context="#stay"/>
|
||||||
|
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<context name="Expect Expression" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Error">
|
||||||
|
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||||
|
<DetectChar attribute="Normal" char="=" context="Expression"/>
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<context name="Expect Assignment" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Error">
|
||||||
|
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||||
|
<RegExpr attribute="Name" String="[_a-zA-Z]\w*" context="Expect Expression"/>
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<context name="After LD" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Expression">
|
||||||
|
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
|
||||||
|
<DetectChar attribute="Comment" char="#" context="Error"/>
|
||||||
</context>
|
</context>
|
||||||
|
|
||||||
<context name="Error" attribute="Error" lineEndContext="Normal">
|
<context name="Error" attribute="Error" lineEndContext="Normal">
|
||||||
|
|
@ -46,19 +98,21 @@
|
||||||
<context name="Quoted String" attribute="String" lineEndContext="Error">
|
<context name="Quoted String" attribute="String" lineEndContext="Error">
|
||||||
<StringDetect attribute="String" String="\\" context="#stay"/>
|
<StringDetect attribute="String" String="\\" context="#stay"/>
|
||||||
<RegExpr attribute="String" String="\\\"" context="#stay"/>
|
<RegExpr attribute="String" String="\\\"" context="#stay"/>
|
||||||
<DetectChar char=""" attribute="String" context="Normal"/>
|
<DetectChar char=""" attribute="String" context="#pop"/>
|
||||||
</context>
|
</context>
|
||||||
|
|
||||||
<context name="Apostrophed String" attribute="Raw String" lineEndContext="Error">
|
<context name="Apostrophed String" attribute="Raw String" lineEndContext="Error">
|
||||||
<StringDetect attribute="String" String="\\" context="#stay"/>
|
<StringDetect attribute="String" String="\\" context="#stay"/>
|
||||||
<RegExpr attribute="String" String="\\\'" context="#stay"/>
|
<RegExpr attribute="String" String="\\\'" context="#stay"/>
|
||||||
<DetectChar char="'" attribute="Raw String" context="Normal"/>
|
<DetectChar char="'" attribute="Raw String" context="#pop"/>
|
||||||
</context>
|
</context>
|
||||||
|
|
||||||
</contexts>
|
</contexts>
|
||||||
|
|
||||||
<itemDatas>
|
<itemDatas>
|
||||||
|
|
||||||
<itemData name="Normal Text" defStyleNum="dsNormal"/>
|
<itemData name="Normal Text" defStyleNum="dsNormal"/>
|
||||||
|
<itemData name="Name" defStyleNum="dsNormal"/>
|
||||||
|
|
||||||
<itemData name="Comment" defStyleNum="dsComment"/>
|
<itemData name="Comment" defStyleNum="dsComment"/>
|
||||||
<itemData name="Float" defStyleNum="dsFloat"/>
|
<itemData name="Float" defStyleNum="dsFloat"/>
|
||||||
|
|
@ -73,4 +127,12 @@
|
||||||
</itemDatas>
|
</itemDatas>
|
||||||
|
|
||||||
</highlighting>
|
</highlighting>
|
||||||
|
|
||||||
|
<general>
|
||||||
|
<comments>
|
||||||
|
<comment name="singleLine" start="#"/>
|
||||||
|
</comments>
|
||||||
|
<keywords casesensitive="1" weakDeliminator="!?"/>
|
||||||
|
</general>
|
||||||
|
|
||||||
</language>
|
</language>
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,13 @@ GDS2Reader::get_string ()
|
||||||
void
|
void
|
||||||
GDS2Reader::get_string (std::string &s) const
|
GDS2Reader::get_string (std::string &s) const
|
||||||
{
|
{
|
||||||
s.assign ((const char *) mp_rec_buf, 0, m_reclen);
|
if (m_reclen == 0) {
|
||||||
|
s.clear ();
|
||||||
|
} else if (mp_rec_buf [m_reclen - 1] != 0) {
|
||||||
|
s.assign ((const char *) mp_rec_buf, m_reclen);
|
||||||
|
} else {
|
||||||
|
s.assign ((const char *) mp_rec_buf, m_reclen - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -350,9 +350,9 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="doc_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Press and hold SHIFT for top view</string>
|
<string>Press and hold SHIFT for top view (<a href="int:/about/25d_view.xml">more</a>)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ D25Camera::~D25Camera ()
|
||||||
void
|
void
|
||||||
D25Camera::init ()
|
D25Camera::init ()
|
||||||
{
|
{
|
||||||
m_fov = 90.0;
|
m_fov = 45.0;
|
||||||
m_cam_azimuth = m_cam_elevation = 0.0;
|
m_cam_azimuth = m_cam_elevation = 0.0;
|
||||||
m_top_view = false;
|
m_top_view = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ public:
|
||||||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||||
{
|
{
|
||||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||||
menu_entries.push_back (lay::menu_item ("lay::d25_view", "d25_view:edit", "tools_menu.post_verification_group", tl::to_string (QObject::tr ("2.5d View"))));
|
menu_entries.push_back (lay::menu_item ("lay::d25_view", "d25_view:edit", "tools_menu.post_verification_group", tl::to_string (QObject::tr ("2.5d View - experimental"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
|
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "layD25View.h"
|
#include "layD25View.h"
|
||||||
#include "layLayoutView.h"
|
#include "layLayoutView.h"
|
||||||
|
#include "layQtTools.h"
|
||||||
|
|
||||||
#include "ui_D25View.h"
|
#include "ui_D25View.h"
|
||||||
|
|
||||||
|
|
@ -53,6 +54,8 @@ D25View::D25View (QWidget *parent)
|
||||||
connect (mp_ui->d25_view, SIGNAL (init_failed ()), this, SLOT (init_failed ()));
|
connect (mp_ui->d25_view, SIGNAL (init_failed ()), this, SLOT (init_failed ()));
|
||||||
|
|
||||||
mp_ui->gl_stack->setCurrentIndex (0);
|
mp_ui->gl_stack->setCurrentIndex (0);
|
||||||
|
|
||||||
|
lay::activate_help_links (mp_ui->doc_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
D25View::~D25View ()
|
D25View::~D25View ()
|
||||||
|
|
|
||||||
|
|
@ -246,40 +246,23 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// compute vector of line of sight
|
double d = event->angleDelta ().y () * (1.0 / (90 * 16));
|
||||||
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
|
|
||||||
|
|
||||||
// by definition the ray goes through the camera position
|
|
||||||
QVector3D hp = hit_point_with_scene (ray.second);
|
|
||||||
|
|
||||||
if (! (event->modifiers () & Qt::ControlModifier)) {
|
if (! (event->modifiers () & Qt::ControlModifier)) {
|
||||||
|
|
||||||
// No Ctrl is closeup
|
// No Ctrl is "move horizontally along the azimuth axis"
|
||||||
|
|
||||||
double f = event->angleDelta ().y () * (1.0 / (90 * 8));
|
QMatrix4x4 t;
|
||||||
m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second;
|
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
||||||
|
QVector3D cd = t.inverted ().map (QVector3D (0, 0, cam_dist ()));
|
||||||
|
|
||||||
|
m_displacement += d * cd;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// "Ctrl" is zoom
|
// "Ctrl" is zoom
|
||||||
|
|
||||||
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
|
m_scale_factor *= exp (d);
|
||||||
|
|
||||||
QVector3D initial_displacement = m_displacement;
|
|
||||||
QVector3D displacement = m_displacement;
|
|
||||||
|
|
||||||
m_scale_factor *= f;
|
|
||||||
displacement += hp * (1.0 - f) / m_scale_factor;
|
|
||||||
|
|
||||||
// normalize the scene translation so the scene does not "flee"
|
|
||||||
|
|
||||||
QMatrix4x4 ct = cam_trans ();
|
|
||||||
initial_displacement = ct.map (initial_displacement);
|
|
||||||
displacement = ct.map (displacement);
|
|
||||||
|
|
||||||
lay::normalize_scene_trans (cam_perspective (), displacement, m_scale_factor, initial_displacement.z ());
|
|
||||||
|
|
||||||
m_displacement = ct.inverted ().map (displacement);
|
|
||||||
|
|
||||||
emit scale_factor_changed (m_scale_factor);
|
emit scale_factor_changed (m_scale_factor);
|
||||||
|
|
||||||
|
|
@ -294,8 +277,65 @@ void
|
||||||
D25ViewWidget::keyPressEvent (QKeyEvent *event)
|
D25ViewWidget::keyPressEvent (QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (event->key () == Qt::Key_Shift) {
|
if (event->key () == Qt::Key_Shift) {
|
||||||
|
|
||||||
mp_mode.reset (0);
|
mp_mode.reset (0);
|
||||||
set_top_view (true);
|
set_top_view (true);
|
||||||
|
|
||||||
|
} else if (event->key () == Qt::Key_Up || event->key () == Qt::Key_Down) {
|
||||||
|
|
||||||
|
if (! top_view () && (event->modifiers () & Qt::ControlModifier) != 0) {
|
||||||
|
|
||||||
|
// Ctrl + up/down changes elevation
|
||||||
|
|
||||||
|
double d = (event->key () == Qt::Key_Up ? 2 : -2);
|
||||||
|
|
||||||
|
set_cam_elevation (std::max (-90.0, std::min (90.0, cam_elevation () + d)));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Move "into" or "out"
|
||||||
|
|
||||||
|
double d = (event->key () == Qt::Key_Up ? 0.1 : -0.1);
|
||||||
|
|
||||||
|
QMatrix4x4 t;
|
||||||
|
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
||||||
|
QVector3D cd = t.inverted ().map (QVector3D (0, 0, cam_dist ()));
|
||||||
|
|
||||||
|
set_displacement (displacement () + d * cd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (event->key () == Qt::Key_Left || event->key () == Qt::Key_Right) {
|
||||||
|
|
||||||
|
if (! top_view () && (event->modifiers () & Qt::ControlModifier) != 0) {
|
||||||
|
|
||||||
|
// Ctrl + left/right changes azumith
|
||||||
|
|
||||||
|
double d = (event->key () == Qt::Key_Right ? 2 : -2);
|
||||||
|
|
||||||
|
double a = cam_azimuth () + d;
|
||||||
|
if (a < -180.0) {
|
||||||
|
a += 360.0;
|
||||||
|
} else if (a > 180.0) {
|
||||||
|
a -= 360.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_cam_azimuth (a);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Move "left" and "right"
|
||||||
|
|
||||||
|
double d = (event->key () == Qt::Key_Left ? 0.1 : -0.1);
|
||||||
|
|
||||||
|
QMatrix4x4 t;
|
||||||
|
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
||||||
|
QVector3D cd = t.inverted ().map (QVector3D (cam_dist (), 0, 0));
|
||||||
|
|
||||||
|
set_displacement (displacement () + d * cd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -435,17 +475,17 @@ namespace {
|
||||||
|
|
||||||
const db::D25LayerInfo *operator() (lay::LayoutView *view, int cv_index, int layer_index)
|
const db::D25LayerInfo *operator() (lay::LayoutView *view, int cv_index, int layer_index)
|
||||||
{
|
{
|
||||||
std::map<int, std::map<int, const db::D25LayerInfo *> >::const_iterator c = m_cache.find (cv_index);
|
std::map<int, std::map<int, db::D25LayerInfo> >::const_iterator c = m_cache.find (cv_index);
|
||||||
if (c != m_cache.end ()) {
|
if (c != m_cache.end ()) {
|
||||||
std::map<int, const db::D25LayerInfo *>::const_iterator l = c->second.find (layer_index);
|
std::map<int, db::D25LayerInfo>::const_iterator l = c->second.find (layer_index);
|
||||||
if (l != c->second.end ()) {
|
if (l != c->second.end ()) {
|
||||||
return l->second;
|
return &l->second;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, const db::D25LayerInfo *> &lcache = m_cache [cv_index];
|
std::map<int, db::D25LayerInfo> &lcache = m_cache [cv_index];
|
||||||
|
|
||||||
const db::D25TechnologyComponent *comp = 0;
|
const db::D25TechnologyComponent *comp = 0;
|
||||||
|
|
||||||
|
|
@ -457,16 +497,18 @@ namespace {
|
||||||
|
|
||||||
if (comp) {
|
if (comp) {
|
||||||
|
|
||||||
std::map<db::LayerProperties, const db::D25LayerInfo *, db::LPLogicalLessFunc> zi_by_lp;
|
std::map<db::LayerProperties, db::D25LayerInfo, db::LPLogicalLessFunc> zi_by_lp;
|
||||||
for (db::D25TechnologyComponent::const_iterator i = comp->begin (); i != comp->end (); ++i) {
|
|
||||||
zi_by_lp.insert (std::make_pair (i->layer (), i.operator-> ()));
|
db::D25TechnologyComponent::layers_type layers = comp->compile_from_source ();
|
||||||
|
for (db::D25TechnologyComponent::layers_type::const_iterator i = layers.begin (); i != layers.end (); ++i) {
|
||||||
|
zi_by_lp.insert (std::make_pair (i->layer (), *i));
|
||||||
}
|
}
|
||||||
|
|
||||||
const db::Layout &ly = cv->layout ();
|
const db::Layout &ly = cv->layout ();
|
||||||
for (int l = 0; l < int (ly.layers ()); ++l) {
|
for (int l = 0; l < int (ly.layers ()); ++l) {
|
||||||
if (ly.is_valid_layer (l)) {
|
if (ly.is_valid_layer (l)) {
|
||||||
const db::LayerProperties &lp = ly.get_properties (l);
|
const db::LayerProperties &lp = ly.get_properties (l);
|
||||||
std::map<db::LayerProperties, const db::D25LayerInfo *, db::LPLogicalLessFunc>::const_iterator z = zi_by_lp.find (lp);
|
std::map<db::LayerProperties, db::D25LayerInfo, db::LPLogicalLessFunc>::const_iterator z = zi_by_lp.find (lp);
|
||||||
if (z == zi_by_lp.end () && ! lp.name.empty ()) {
|
if (z == zi_by_lp.end () && ! lp.name.empty ()) {
|
||||||
// If possible, try by name only
|
// If possible, try by name only
|
||||||
z = zi_by_lp.find (db::LayerProperties (lp.name));
|
z = zi_by_lp.find (db::LayerProperties (lp.name));
|
||||||
|
|
@ -485,7 +527,7 @@ namespace {
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<int, std::map<int, const db::D25LayerInfo *> > m_cache;
|
std::map<int, std::map<int, db::D25LayerInfo> > m_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -955,9 +997,12 @@ D25ViewWidget::paintGL ()
|
||||||
|
|
||||||
vertexes.add (-0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
vertexes.add (-0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||||
vertexes.add (0.0, 0.0, -0.8 * compass_rad);
|
vertexes.add (0.0, 0.0, -0.8 * compass_rad);
|
||||||
|
vertexes.add (0.0, 0.0, -0.8 * compass_rad);
|
||||||
vertexes.add (0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
vertexes.add (0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||||
|
vertexes.add (0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||||
|
vertexes.add (-0.25 * compass_rad, 0.0, 0.6 * compass_rad);
|
||||||
|
|
||||||
vertexes.draw_to (this, positions, GL_TRIANGLES);
|
vertexes.draw_to (this, positions, GL_LINES);
|
||||||
|
|
||||||
// draw base plane
|
// draw base plane
|
||||||
|
|
||||||
|
|
@ -1029,8 +1074,8 @@ D25ViewWidget::paintGL ()
|
||||||
|
|
||||||
glDisable (GL_DEPTH_TEST);
|
glDisable (GL_DEPTH_TEST);
|
||||||
|
|
||||||
int cube_size = 64;
|
int cube_size = 32;
|
||||||
int cube_margin = 20;
|
int cube_margin = 40;
|
||||||
|
|
||||||
QMatrix4x4 into_top_right_corner;
|
QMatrix4x4 into_top_right_corner;
|
||||||
into_top_right_corner.translate (1.0 - 2.0 / width () * (cube_margin + cube_size / 2), 1.0 - 2.0 / height () * (cube_margin + cube_size / 2));
|
into_top_right_corner.translate (1.0 - 2.0 / width () * (cube_margin + cube_size / 2), 1.0 - 2.0 / height () * (cube_margin + cube_size / 2));
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Move constructor
|
||||||
|
*
|
||||||
|
* See operator= for a description of the copy operation.
|
||||||
|
*/
|
||||||
|
reuse_vector (reuse_vector &&d)
|
||||||
|
{
|
||||||
|
mp_start = d.mp_start; d.mp_start = 0;
|
||||||
|
mp_finish = d.mp_finish; d.mp_finish = 0;
|
||||||
|
mp_capacity = d.mp_capacity; d.mp_capacity = 0;
|
||||||
|
mp_rdata = d.mp_rdata; d.mp_rdata = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
|
|
@ -562,6 +575,20 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assignment (move)
|
||||||
|
*/
|
||||||
|
reuse_vector &operator= (reuse_vector &&d)
|
||||||
|
{
|
||||||
|
if (&d != this) {
|
||||||
|
mp_start = d.mp_start; d.mp_start = 0;
|
||||||
|
mp_finish = d.mp_finish; d.mp_finish = 0;
|
||||||
|
mp_capacity = d.mp_capacity; d.mp_capacity = 0;
|
||||||
|
mp_rdata = d.mp_rdata; d.mp_rdata = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assignment
|
* @brief Assignment
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,11 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit vector (const tl::vector<T> &d) : base (d) { }
|
explicit vector (const tl::vector<T> &d) : base (d) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Move constructor
|
||||||
|
*/
|
||||||
|
explicit vector (const tl::vector<T> &&d) : base (d) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assignment
|
* @brief Assignment
|
||||||
*/
|
*/
|
||||||
|
|
@ -71,6 +76,17 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assignment (Move)
|
||||||
|
*/
|
||||||
|
vector &operator= (const tl::vector<T> &&d)
|
||||||
|
{
|
||||||
|
if (&d != this) {
|
||||||
|
base::operator= (d);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialization with value and length
|
* @brief Initialization with value and length
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
source $drc_test_source
|
||||||
|
target $drc_test_target
|
||||||
|
|
||||||
|
if $drc_test_deep
|
||||||
|
deep
|
||||||
|
end
|
||||||
|
|
||||||
|
l1 = input(1, 0)
|
||||||
|
l1.output(1, 0)
|
||||||
|
|
||||||
|
to_fill = extent - l1
|
||||||
|
|
||||||
|
fp1 = fill_pattern("FP1").shape(10, 0, box(0, 0, 800.nm, 800.nm)).origin(-100.nm, -100.nm)
|
||||||
|
to_fill = to_fill.fill_with_left(fp1, hstep(1.um), vstep(200.nm, 1.um), multi_origin)
|
||||||
|
|
||||||
|
fp2 = fill_pattern("FP2").shape(10, 0, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm)
|
||||||
|
to_fill = to_fill.fill_with_left(fp2, hstep(0.5.um), vstep(100.nm, 0.5.um), multi_origin)
|
||||||
|
|
||||||
|
fp3 = fill_pattern("FP3").shape(10, 0, box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm)
|
||||||
|
to_fill = to_fill.fill_with_left(fp3, hstep(0.25.um), vstep(50.nm, 0.25.um), multi_origin)
|
||||||
|
|
||||||
|
to_fill.output(100, 0)
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
source $drc_test_source
|
||||||
|
target $drc_test_target
|
||||||
|
|
||||||
|
if $drc_test_deep
|
||||||
|
deep
|
||||||
|
end
|
||||||
|
|
||||||
|
tiles(20, 20)
|
||||||
|
|
||||||
|
l1 = input(1, 0)
|
||||||
|
l1.output(1, 0)
|
||||||
|
|
||||||
|
to_fill = extent - l1
|
||||||
|
|
||||||
|
fp1 = fill_pattern("FP1").shape(10, 0, box(0, 0, 800.nm, 800.nm)).origin(-100.nm, -100.nm)
|
||||||
|
to_fill = to_fill.fill_with_left(fp1, hstep(1.um), vstep(200.nm, 1.um), multi_origin)
|
||||||
|
|
||||||
|
fp2 = fill_pattern("FP2").shape(10, 0, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm)
|
||||||
|
to_fill = to_fill.fill_with_left(fp2, hstep(0.5.um), vstep(100.nm, 0.5.um), multi_origin)
|
||||||
|
|
||||||
|
fp3 = fill_pattern("FP3").shape(10, 0, box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm)
|
||||||
|
to_fill = to_fill.fill_with_left(fp3, hstep(0.25.um), vstep(50.nm, 0.25.um), multi_origin)
|
||||||
|
|
||||||
|
to_fill.output(100, 0)
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue