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
|
||||
Enhanced API for ObjectInstPath
|
||||
0.27 (2021-04-xx):
|
||||
|
||||
* Enhancements: Numerous new functions for the RBA and pya API
|
||||
Some highlights:
|
||||
* "Texts" for text collections (similar for Edges/EdgePairs/Region)
|
||||
* New modes for blending layout files - see GitHub issue #666
|
||||
* New function Cell#transform - see GitHub issue #598
|
||||
* New functions for Image (read, write, clear)
|
||||
* New functions for Region and Edges correlating with the new DRC features
|
||||
* Multi-cell hierarchical copy/move of trees - will maintain shared instances
|
||||
* RBA: iterators are now automatically made available as Enumerable
|
||||
* All functions having a void return specification now return self (allows chaining)
|
||||
* More functions for manipulating selections (LayoutView#select_all etc.)
|
||||
* Spline interpolation code available in new "Utils" namespace
|
||||
* QByteArray support, mapping to Python byte arrays
|
||||
* MainWindow#set_key_bindings, MainWindow#get_key_bindings, MainWindow#set_menu_items_hidden etc.
|
||||
* New class RecursiveInstanceIterator (similar to RecursiveShapeIterator, but acts on instances)
|
||||
* Deep vs. flat operations do not always flatten out now (flat vs. deep does however)
|
||||
* Global transformations for inputs
|
||||
* Enhancements: New DRC features
|
||||
Some highlights:
|
||||
* Better support for texts - "text layers"
|
||||
* Combined AND+NOT feature for separating regions into inside and outside part
|
||||
* "max_vertex_count" and "max_area_ratio" configuration options
|
||||
* "forget" for memory optimization
|
||||
* Shielding is optional now for some DRC functions
|
||||
* "interact" now has a count filter
|
||||
* In verbose more, figure counts and more information is printed
|
||||
* Generic DRC function and complex DRC operations: for details search "Universal DRC" in documentation
|
||||
* "not_opposite" and "rect_filter" options for some DRC functions
|
||||
* "enclosing" (selects polygons entirely enclosing others)
|
||||
* New filters for polygons: squares, non_squares, area ratio, bbox aspect ratio
|
||||
* More intuitive specification of projection limits ("projecting < 2.um")
|
||||
* "with_holes" and "without_holes", also with count
|
||||
* Density check is included now ("with_densitiy", "without_density")
|
||||
* "split_..." functions give interacting/non-interacting sets in one step
|
||||
* Better support for generic transformations as Matrix2d and Matrix3d
|
||||
* "fill" and "fill_with_left" functions for dummy fill
|
||||
* NO "connected" feature yet. Sorry. Had to drop it to finish this release.
|
||||
* Enhancements: new LVS features
|
||||
Some highlights:
|
||||
* Improved netlist and LVS result browser (infinite-depth browsing)
|
||||
* Improved circuit match algorithm
|
||||
* Case insensitive handling of object names for SPICE netlists
|
||||
* Probe feature fixed in flat mode
|
||||
* "connect_explicit": for details search "connect_explicit" in documentation
|
||||
* Enhancements: New features for images
|
||||
Some highlights:
|
||||
* New menu item: show and hide all images - see GitHub issue #535
|
||||
* False color nodes now can have a left and right color allowing color steps
|
||||
* Persistance of images through a special file format: "lyimg" (XML based)
|
||||
* Enhancements: LEF/DEF reader
|
||||
Some highlights:
|
||||
* Support for layer map files
|
||||
* More complete spec support (e.g. FILL, MASK, FOREIGN, DO/BY/STEP ...)
|
||||
* Several bug fixes, e.g. routing layer switch for VIAs
|
||||
* Some functions also act on the transient selection (less mouse clicks)
|
||||
* Enhancements: Layout editing and rulers
|
||||
Some highlights:
|
||||
* Object properties now are changed without having to commit the dialogs
|
||||
* Dockable editor options windows
|
||||
* "Recently used" list
|
||||
* A "distribute objects" feature (Edit/Selection/Distribute)
|
||||
* Snap highlighting
|
||||
* Mouse tracking cursor indicates grid- and object-snapped location
|
||||
* Enhancements: Help browser
|
||||
* Bookmarks
|
||||
* Search in page (Ctrl+F)
|
||||
* Enhancement: Improved fill tool
|
||||
The fill tool now also supports skewed fill pattern repetitions
|
||||
* Enhancement: Ability to utilize a LayoutView as a Widget
|
||||
Standalone instantiation of a LayoutView object is
|
||||
supported now. So it becomes possible to create
|
||||
custom MainWindow UIs and embed a layout view there.
|
||||
* Enhancement: Improved layer and cell list filtering and searching
|
||||
* Enhancement: Experimental 3d (called 2.5d) view of layout
|
||||
For details search "2.5d View" in documentation.
|
||||
* Enhancement: Improved performance on sea of instances for OASIS files
|
||||
Iterated OASIS instances are stored and handled in a leaner way in viewer mode
|
||||
* Enhancement: Buddy scripts can concatenate files with "+" for input
|
||||
Concatenation happens by "blending files". Beware of the risk this implies.
|
||||
* Enhancement: Layer maps now support n:m layer mapping
|
||||
This allows mapping n input layers to one logical layer (merging) and also
|
||||
one input layer to m logical ones (clone layer). This applies to the
|
||||
buddy scripts and layer maps inside KLayout's reader.
|
||||
* Enhancement: include mechanism for easy include of files into DRC/LVS scripts
|
||||
This is a plain text substitution feature. Don't use it for Ruby or Python
|
||||
scripts (the preferred way is still require/import). But it's a quick way
|
||||
to include partial DRC and LVS scripts without having to worry about variable
|
||||
scope. For details see "Including other files" in the documentation under:
|
||||
KLayout User Manual/Design Rule Check (DRC)/DRC Runsets.
|
||||
* Bugfix: %GITHUB%/issues/750
|
||||
PCB gerber import: Incorrect handling of D02 operations.
|
||||
* Bugfix: %GITHUB%/issues/740
|
||||
Bug in the "smooth" function.
|
||||
* Enhancement: %GITHUB%/issues/691
|
||||
Technology specific libraries: library name resolution based on technology.
|
||||
* Enhancement: %GITHUB%/issues/666
|
||||
Controlling the way a layout reader integrates cells into an existing layout.
|
||||
* Bugfix: %GITHUB%/issues/663
|
||||
Deep mode DRC: separation from "inside" gives wrong errors.
|
||||
* Enhancement: %GITHUB%/issues/648
|
||||
LVS could not do "connect_implicit" with global nets.
|
||||
* Bugfix: %GITHUB%/issues/609
|
||||
Internal error on net extraction.
|
||||
* Enhancement: %GITHUB%/issues/598
|
||||
Plain transformation of cell missing.
|
||||
* Enhancement: %GITHUB%/issues/588
|
||||
RBA/PYA: Provide event when a net is selected in the netlist browser.
|
||||
* Enhancement: %GITHUB%/issues/563
|
||||
True support for text objects in DRC/LVS (text layers).
|
||||
* Enhancement: %GITHUB%/issues/558
|
||||
Edges#extents, Texts#extents and EdgePairs#extents now
|
||||
work hierarchically in deep mode. In DRC, this means,
|
||||
"extents" is a deep-enabled method now.
|
||||
* Enhancement: %GITHUB%/issues/563
|
||||
True support for text objects in DRC/LVS (text layers)
|
||||
* Enhancement: ability to utilize a LayoutView as a Widget
|
||||
Standalone instantiation of a LayoutView object is
|
||||
supported now. So it becomes possible to create
|
||||
custom MainWindow UIs and embed a layout view there.
|
||||
* Enhancement: %GITHUB%/issues/535
|
||||
Image handling enhancements.
|
||||
* Enhancement: %GITHUB%/issues/521
|
||||
Enhanced API for ObjectInstPath.
|
||||
* Enhancement: %GITHUB%/issues/487
|
||||
Difficult to select specific labels for net name assignment in net extraction.
|
||||
Solution involves a more elaborate handling of texts through "text layers.
|
||||
|
||||
0.26.5 (2020-xx-xx):
|
||||
0.26.11 (2021-02-27):
|
||||
|
||||
* Bugfix: %GITHUB%/issues/733
|
||||
Relative path resolution in session files fails when the session file's path contains "+" characters
|
||||
* Enhancement: %GITHUB%/issues/730
|
||||
Support of class 'QUiLoader' in PYA and RBA
|
||||
* Bugfix: %GITHUB%/issues/728
|
||||
Fails to build on Debian hppa: uses non-standard sa_restorer field of struct sigaction
|
||||
* Bugfix: %GITHUB%/issues/726
|
||||
Crash on LayoutView#clear_selection on Linux.
|
||||
* Bugfix: %GITHUB%/issues/723
|
||||
Backup scheme wasn't working correctly with a single file without path
|
||||
given as command line argument.
|
||||
|
||||
0.26.10 (2020-02-02):
|
||||
|
||||
* Enhancement: %GITHUB%/issues/720
|
||||
"Safe save" and backups: when saving files, the file is only overwritten after
|
||||
the save terminated successfully. This will avoid loss of data for full volumes
|
||||
or network share dropouts. In addition, a configurable number of back files can
|
||||
be kept (see File/Setup: Application/General).
|
||||
* Bugfix: %GITHUB%/issues/718
|
||||
GDS export issue fixed (breaking of polygons was filling holes)
|
||||
* Bugfix: %GITHUB%/issues/709
|
||||
LVS compare enters infinite loop when it encounters two entirely identical subcircuits
|
||||
* Bugfix: %GITHUB%/issues/708
|
||||
Qt binding: missing support for binary strings as QByteArray representative
|
||||
* Bugfix: %GITHUB%/issues/707
|
||||
QJsonValue's string constructor is ambiguous
|
||||
* Bugfix: %GITHUB%/issues/704
|
||||
Rational Splines not supported DXF
|
||||
* Bugfix: %GITHUB%/issues/693
|
||||
MAGIC files won't find subcells when reading from command line
|
||||
* Bugfix: HTTP stream reading issue with redirect
|
||||
At least on MacOS a segfault happened when reading HTTP stream data
|
||||
(e.g. for package manager) from addresses which are redirected.
|
||||
* Enhancement: Removed %APPDATA% from DLL search path on Windows
|
||||
This will avoid installation poisoning by the one from %APPDATA%
|
||||
(which ironically is the default installation path). Eventually
|
||||
multiple versions can be used in parallel.
|
||||
|
||||
0.26.9 (2020-11-27):
|
||||
|
||||
* Bugfix: %GITHUB%/issues/658
|
||||
Menu items were not put into the right place on MacOS.
|
||||
* Bugfix: %GITHUB%/issues/652
|
||||
"M" factor scaling was not working for Spice reader.
|
||||
* Bugfix: %GITHUB%/issues/651
|
||||
Fixed an issue with DRC "select".
|
||||
* Bugfix: %GITHUB%/issues/647
|
||||
Text orientation was not considered properly in search & replace
|
||||
* Bugfix: %GITHUB%/issues/646
|
||||
A potential crash was fixed happening when a PCell
|
||||
library is deleted
|
||||
* Bugfix: Display bug
|
||||
Cell placements with small magnification factors (such that the
|
||||
viewport dimensions exceeded the DBU space when seem from inside
|
||||
the cell) lead to display errors.
|
||||
|
||||
0.26.8 (2020-09-15):
|
||||
|
||||
* Enhancement: %GITHUB%/issues/639
|
||||
A new method is available which enables copying of multiple cells
|
||||
into a target layout while maintaining common subcells are single
|
||||
cells.
|
||||
* Bugfix: %GITHUB%/issues/637
|
||||
Points have not been selected properly when inside mirrored subcells
|
||||
in partial edit mode.
|
||||
* Bugfix: %GITHUB%/issues/629
|
||||
Qt5 QTimer timeout signal was not available to Python or Ruby.
|
||||
This also applied to all "private" signals of Qt5. QTimer is just
|
||||
one important example for this case.
|
||||
* Bugfix: %GITHUB%/issues/617
|
||||
A problem with pseudo-const Python/Ruby objects in the netlist API
|
||||
was fixed.
|
||||
* Bugfix: %GITHUB%/issues/615
|
||||
Basic authentication for package manager now uses UTF-8 encoding.
|
||||
Most servers expect this kind of encoding today. UTF password
|
||||
characters are supported this way.
|
||||
|
||||
0.26.7 (2020-07-07):
|
||||
|
||||
* Bugfix: %GITHUB%/issues/381 and more
|
||||
Some bugs fixed that happened specifically on MacOS.
|
||||
1.) A segfault that happened in LVS
|
||||
2.) Some classes were not properly registered for usage in scripts.
|
||||
* Bugfix: %GITHUB%/issues/493
|
||||
LVS asserted on MacOS
|
||||
* Enhancement: %GITHUB%/issues/586
|
||||
As a safety feature, the stream writers now refuse to write layouts
|
||||
with cells carrying the same names. Writing such layers would result
|
||||
in corrupted or invalid layout files.
|
||||
* Bugfix: %GITHUB%/issues/589 (tentative)
|
||||
On Anaconda-based builds for MacOS 10.15 (Catalina) a loss of instances
|
||||
was observed. This could be traced down to compiler/library incompatibilities
|
||||
but not further.
|
||||
* Enhancements: %GITHUB%/issues/591
|
||||
Two enhancements in the macro editor:
|
||||
1.) A crash happening when adding a new location was fixed
|
||||
2.) The template selection popup can now be disabled by dismissing the
|
||||
tip dialog.
|
||||
* Bugfix: %GITHUB%/issues/592
|
||||
Reading a file into a layout with unnamed layers caused problems with
|
||||
layer mapping specs.
|
||||
* Bugfix: %GITHUB%/issues/596
|
||||
Library#_destroy was crashing the application. As this function must not
|
||||
be called, it's rerouted to "nothing" for backward compatibility.
|
||||
* Enhancement: %GITHUB%/issues/603
|
||||
The "adjust origin" feature now allows specifying the target
|
||||
coordinates for the adjustment.
|
||||
* Bugfix: %GITHUB%/issues/610
|
||||
An internal error happened for certain hierarchical configurations on
|
||||
netlist extraction.
|
||||
* Enhancement: LVS netlist compare
|
||||
The algorithm was improved to provide better reproducibility. The
|
||||
detection of matching paths in the presence of ambiguities was
|
||||
improved.
|
||||
In addition, the netlist compare now favours net names for resolving
|
||||
ambiguities. So if nets are named the same in the layout and the
|
||||
schematic, ambiguities are resolved based on these names. This is
|
||||
usually more efficient. A new function is available to turn this
|
||||
feature off: "consider_net_names(false)".
|
||||
|
||||
0.26.6 (2020-06-05):
|
||||
|
||||
* Enhancement: %GITHUB%/issues/522
|
||||
Skip comment lines with // in RVE DB reader
|
||||
* Bugfix: %GITHUB%/issues/547
|
||||
Doc fixes, better error messages on some Shape methods
|
||||
* Bugfix: %GITHUB%/issues/554
|
||||
Using 64bit coordinates on RVE reader to avoid overflow
|
||||
* Bugfix: %GITHUB%/issues/565
|
||||
Spice reader: .global should not add pin if the signal
|
||||
isn't used in a subcircuit
|
||||
* Bugfix: %GITHUB%/issues/568 and %GITHUB%/issues/578
|
||||
A CIF reader and writer bug was fixed
|
||||
* Bugfix: %GITHUB%/issues/570 and %GITHUB%/issues/579
|
||||
Perimenter can be included in antenna area for the
|
||||
antenna check. This also includes a mode in which only
|
||||
the perimeter is considered.
|
||||
* Enhancement: %GITHUB%/issues/560
|
||||
A library can be associated with multiple technologies now.
|
||||
* Bugfix: width of cell and library side panels could not be
|
||||
reduced below the width of the selection boxes in the
|
||||
header
|
||||
* Bugfix: cell view selection header text did not get updated
|
||||
when saving the layout to a different file
|
||||
|
||||
0.26.5 (2020-05-02):
|
||||
|
||||
* Bugfix: %GITHUB%/issues/539
|
||||
An internal error happened on netlist flatten sometimes
|
||||
|
|
@ -28,6 +285,8 @@
|
|||
* Bugfix: %GITHUB%/issues/544
|
||||
Duplicate .global statements in SPICE netlists created
|
||||
duplicate pins
|
||||
* Bugfix: %GITHUB%/issues/548
|
||||
A shielding issue was fixed for DRC space measurements
|
||||
* Bugfix: diff tool bug with paths
|
||||
Differences in path points where no reported
|
||||
* Enhancement: documentation clarifications and typos fixed
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ PropertiesPage::swap_points_clicked ()
|
|||
y1->setText (ty1);
|
||||
y2->setText (ty2);
|
||||
|
||||
db::Transaction t (manager (), tl::to_string (QObject::tr ("Swap ruler points")));
|
||||
emit edited ();
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +223,6 @@ PropertiesPage::snap_to_layout_clicked ()
|
|||
y2->setText (ys);
|
||||
}
|
||||
|
||||
db::Transaction t (manager (), tl::to_string (snap_p1 ? QObject::tr ("Snap first ruler point") : QObject::tr ("Snap second ruler point")));
|
||||
emit edited ();
|
||||
|
||||
break;
|
||||
|
|
@ -249,7 +247,6 @@ PropertiesPage::snap_to_layout_clicked ()
|
|||
x2->setText (tl::to_qstring (tl::micron_to_string (ee.second.x ())));
|
||||
y2->setText (tl::to_qstring (tl::micron_to_string (ee.second.y ())));
|
||||
|
||||
db::Transaction t (manager (), tl::to_string (QObject::tr ("Snap both ruler points")));
|
||||
emit edited ();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1274,8 +1274,9 @@ Service::end_move (const db::DPoint &, lay::angle_constraint_type)
|
|||
// compute moved object and replace
|
||||
ant::Object *rnew = new ant::Object (*robj);
|
||||
rnew->transform (m_trans);
|
||||
int new_id = rnew->id ();
|
||||
mp_view->annotation_shapes ().replace (s->first, db::DUserObject (rnew));
|
||||
annotation_changed_event (rnew->id ());
|
||||
annotation_changed_event (new_id);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -760,6 +760,15 @@ public:
|
|||
// .. nothing else ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
box_tree (box_tree &&b)
|
||||
: m_objects (b.m_objects), m_elements (b.m_elements), mp_root (b.mp_root)
|
||||
{
|
||||
b.mp_root = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
|
|
@ -774,6 +783,21 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment (move)
|
||||
*/
|
||||
box_tree &operator= (box_tree &&b)
|
||||
{
|
||||
clear ();
|
||||
m_objects = b.m_objects;
|
||||
m_elements = b.m_elements;
|
||||
if (b.mp_root) {
|
||||
mp_root = b.mp_root;
|
||||
b.mp_root = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The destructor
|
||||
*/
|
||||
|
|
@ -1729,6 +1753,15 @@ public:
|
|||
// .. nothing else ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
unstable_box_tree (unstable_box_tree &&b)
|
||||
: m_objects (b.m_objects), mp_root (b.mp_root)
|
||||
{
|
||||
b.mp_root = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
|
|
@ -1742,6 +1775,20 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment (move)
|
||||
*/
|
||||
unstable_box_tree &operator= (unstable_box_tree &&b)
|
||||
{
|
||||
clear ();
|
||||
m_objects = b.m_objects;
|
||||
if (b.mp_root) {
|
||||
mp_root = b.mp_root;
|
||||
b.mp_root = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The destructor
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -357,10 +357,7 @@ CompoundRegionMultiInputOperationNode::init ()
|
|||
|
||||
CompoundRegionMultiInputOperationNode::~CompoundRegionMultiInputOperationNode ()
|
||||
{
|
||||
for (tl::shared_collection<CompoundRegionOperationNode>::iterator i = m_children.begin (); i != m_children.end (); ++i) {
|
||||
delete i.operator-> ();
|
||||
}
|
||||
m_children.clear ();
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
|||
// provide some explanation for the initialization
|
||||
m_src =
|
||||
"# Provide z stack information here\n"
|
||||
"#\n"
|
||||
"# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\n"
|
||||
"# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n"
|
||||
"# Named arguments are:\n"
|
||||
|
|
@ -127,7 +128,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
|||
"# zstop The upper z position of the extruded layer in µm\n"
|
||||
"# height The height of the extruded layer in µm\n"
|
||||
"#\n"
|
||||
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart', "
|
||||
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart',\n"
|
||||
"# the upper level of the previous layer will be used.\n"
|
||||
"#\n"
|
||||
"# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\n"
|
||||
|
|
@ -139,25 +140,52 @@ D25TechnologyComponent::D25TechnologyComponent ()
|
|||
"# 1: zstop=1.5, zstart=0.5 # same with named parameters\n"
|
||||
"# 1: height=1.0, zstop=1.5 # same with z stop minus height\n"
|
||||
"# 1: 1.0 zstop=1.5 # same with height as unnamed parameter\n"
|
||||
"#\n"
|
||||
"# VARIABLES\n"
|
||||
"#\n"
|
||||
"# You can declare variables with:\n"
|
||||
"# var name = value\n"
|
||||
"#\n"
|
||||
"# You can use variables inside numeric expressions.\n"
|
||||
"# Example:\n"
|
||||
"# var hmetal = 0.48\n"
|
||||
"# 7/0: 0.5 0.5+hmetal*2 # 2x thick metal\n"
|
||||
"#\n"
|
||||
"# You cannot use variables inside layer specifications currently.\n"
|
||||
"#\n"
|
||||
"# CONDITIONALS\n"
|
||||
"#\n"
|
||||
"# You can enable or disable branches of the table using 'if', 'else', 'elseif' and 'end':\n"
|
||||
"# Example:\n"
|
||||
"# var thick_m1 = true\n"
|
||||
"# if thickm1\n"
|
||||
"# 1: 0.5 1.5\n"
|
||||
"# else\n"
|
||||
"# 1: 0.5 1.2\n"
|
||||
"# end\n"
|
||||
"\n"
|
||||
;
|
||||
}
|
||||
|
||||
D25TechnologyComponent::D25TechnologyComponent (const D25TechnologyComponent &d)
|
||||
: db::TechnologyComponent (d25_component_name (), d25_description ())
|
||||
{
|
||||
m_layers = d.m_layers;
|
||||
m_src = d.m_src;
|
||||
}
|
||||
|
||||
void
|
||||
D25TechnologyComponent::compile_from_source (const std::string &src)
|
||||
D25TechnologyComponent::layers_type
|
||||
D25TechnologyComponent::compile_from_source () const
|
||||
{
|
||||
layers_type layers;
|
||||
|
||||
int current_line = 0;
|
||||
m_layers.clear ();
|
||||
|
||||
try {
|
||||
|
||||
std::vector<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) {
|
||||
|
||||
++current_line;
|
||||
|
|
@ -168,12 +196,86 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
// ignore comments
|
||||
} else if (ex.at_end ()) {
|
||||
// ignore empty lines
|
||||
|
||||
} else if (ex.test ("if")) {
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
conditional_stack.push_back (x.execute ().to_bool ());
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("else")) {
|
||||
|
||||
if (conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'else' without 'if'")));
|
||||
}
|
||||
|
||||
conditional_stack.back () = ! conditional_stack.back ();
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("end")) {
|
||||
|
||||
if (conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'end' without 'if'")));
|
||||
}
|
||||
|
||||
conditional_stack.pop_back ();
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("elsif")) {
|
||||
|
||||
if (conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'elsif' without 'if'")));
|
||||
}
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
conditional_stack.back () = x.execute ().to_bool ();
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (! conditional_stack.empty () && ! conditional_stack.back ()) {
|
||||
|
||||
continue;
|
||||
|
||||
} else if (ex.test ("var")) {
|
||||
|
||||
std::string n;
|
||||
ex.read_name (n);
|
||||
|
||||
ex.expect ("=");
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
eval.set_var (n, x.execute ());
|
||||
|
||||
ex.expect_end ();
|
||||
|
||||
} else if (ex.test ("print")) {
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
ex.expect_end ();
|
||||
|
||||
tl::info << x.execute ().to_string ();
|
||||
|
||||
} else if (ex.test ("error")) {
|
||||
|
||||
tl::Expression x;
|
||||
eval.parse (x, ex);
|
||||
ex.expect_end ();
|
||||
|
||||
throw tl::Exception (x.execute ().to_string ());
|
||||
|
||||
} else {
|
||||
|
||||
db::D25LayerInfo info;
|
||||
if (! m_layers.empty ()) {
|
||||
info.set_zstart (m_layers.back ().zstop ());
|
||||
info.set_zstop (m_layers.back ().zstop ());
|
||||
if (! layers.empty ()) {
|
||||
info.set_zstart (layers.back ().zstop ());
|
||||
info.set_zstop (layers.back ().zstop ());
|
||||
}
|
||||
|
||||
tl::Variant z0, z1, h;
|
||||
|
|
@ -191,16 +293,18 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
break;
|
||||
}
|
||||
|
||||
double pv = 0.0;
|
||||
tl::Expression pvx;
|
||||
|
||||
std::string pn;
|
||||
if (ex.try_read_name (pn)) {
|
||||
ex.expect ("=");
|
||||
ex.read (pv);
|
||||
eval.parse (pvx, ex);
|
||||
} else {
|
||||
ex.read (pv);
|
||||
eval.parse (pvx, ex);
|
||||
}
|
||||
|
||||
double pv = pvx.execute ().to_double ();
|
||||
|
||||
ex.test (",");
|
||||
|
||||
if (pn.empty ()) {
|
||||
|
|
@ -220,7 +324,7 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
if (args.size () == 0) {
|
||||
if (z0.is_nil () && z1.is_nil ()) {
|
||||
if (! h.is_nil ()) {
|
||||
info.set_zstop (info.zstart () + h.to_double ());
|
||||
info.set_zstop (info.zstop () + h.to_double ());
|
||||
}
|
||||
} else if (z0.is_nil ()) {
|
||||
info.set_zstop (z1.to_double ());
|
||||
|
|
@ -239,28 +343,28 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
} else if (args.size () == 1) {
|
||||
if (! h.is_nil ()) {
|
||||
if (! z0.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
|
||||
}
|
||||
if (! z1.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
|
||||
}
|
||||
info.set_zstart (args[0]);
|
||||
info.set_zstop (args[0] + h.to_double ());
|
||||
} else {
|
||||
if (! z1.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
|
||||
}
|
||||
info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]);
|
||||
}
|
||||
} else if (args.size () == 2) {
|
||||
if (! z0.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
|
||||
}
|
||||
if (! z1.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop already given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop already given")));
|
||||
}
|
||||
if (! h.is_nil ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: height implicitly given")));
|
||||
throw tl::Exception (tl::to_string (tr ("Redundant parameters: height implicitly given")));
|
||||
}
|
||||
info.set_zstart (args[0]);
|
||||
info.set_zstop (args[1]);
|
||||
|
|
@ -268,25 +372,30 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
|
|||
throw tl::Exception (tl::to_string (tr ("Too many parameters (max 2)")));
|
||||
}
|
||||
|
||||
m_layers.push_back (info);
|
||||
layers.push_back (info);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! conditional_stack.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("'if', 'else' or 'elsif' without matching 'end'")));
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
|
||||
}
|
||||
|
||||
m_src = src;
|
||||
return layers;
|
||||
}
|
||||
|
||||
std::string
|
||||
D25TechnologyComponent::to_string () const
|
||||
{
|
||||
layers_type layers = compile_from_source ();
|
||||
std::string res;
|
||||
|
||||
for (const_iterator i = begin (); i != end (); ++i) {
|
||||
for (layers_type::const_iterator i = layers.begin (); i != layers.end (); ++i) {
|
||||
if (! res.empty ()) {
|
||||
res += "\n";
|
||||
}
|
||||
|
|
@ -317,11 +426,6 @@ public:
|
|||
virtual tl::XMLElementBase *xml_element () const
|
||||
{
|
||||
return new db::TechnologyComponentXMLElement<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")
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,55 +76,8 @@ public:
|
|||
D25TechnologyComponent (const D25TechnologyComponent &d);
|
||||
|
||||
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);
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
return m_layers.begin ();
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
return m_layers.begin ();
|
||||
}
|
||||
|
||||
const_iterator end () const
|
||||
{
|
||||
return m_layers.end ();
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
return m_layers.end ();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
m_layers.clear ();
|
||||
}
|
||||
|
||||
void erase (iterator p)
|
||||
{
|
||||
m_layers.erase (p);
|
||||
}
|
||||
|
||||
void insert (iterator p, const D25LayerInfo &info)
|
||||
{
|
||||
m_layers.insert (p, info);
|
||||
}
|
||||
|
||||
void add (const D25LayerInfo &info)
|
||||
{
|
||||
m_layers.push_back (info);
|
||||
}
|
||||
|
||||
size_t size () const
|
||||
{
|
||||
return m_layers.size ();
|
||||
}
|
||||
layers_type compile_from_source () const;
|
||||
|
||||
const std::string &src () const
|
||||
{
|
||||
|
|
@ -145,7 +98,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
layers_type m_layers;
|
||||
std::string m_src;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -212,11 +212,6 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
|||
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0")));
|
||||
}
|
||||
|
||||
// disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box
|
||||
if (enhanced_fill && ! glue_box.empty () && ! fp0.box ().enlarged (db::Vector (1, 1)).inside (glue_box)) {
|
||||
enhanced_fill = false;
|
||||
}
|
||||
|
||||
db::Vector kernel_origin (fc_bbox.left (), fc_bbox.bottom ());
|
||||
|
||||
std::vector <db::Polygon> filled_regions;
|
||||
|
|
@ -256,13 +251,21 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
|||
continue;
|
||||
}
|
||||
|
||||
size_t ninsts = 0;
|
||||
// disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box
|
||||
bool ef = enhanced_fill;
|
||||
if (ef && ! glue_box.empty () && ! fp->box ().enlarged (db::Vector (1, 1)).inside (glue_box)) {
|
||||
ef = false;
|
||||
}
|
||||
|
||||
// pick a heuristic "good" starting point in enhanced mode
|
||||
// TODO: this is a pretty weak optimization.
|
||||
db::Point o = origin;
|
||||
if (enhanced_fill) {
|
||||
if (ef) {
|
||||
o = fp->hull () [0];
|
||||
}
|
||||
|
||||
size_t ninsts = 0;
|
||||
|
||||
GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ());
|
||||
|
||||
for (unsigned int i = 0; i < am.area_maps (); ++i) {
|
||||
|
|
@ -454,7 +457,7 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell
|
|||
DB_PUBLIC void
|
||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
||||
const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
||||
{
|
||||
const db::Region *fill_region = &fr;
|
||||
|
||||
|
|
@ -468,7 +471,7 @@ fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fi
|
|||
++iteration;
|
||||
|
||||
remaining.clear ();
|
||||
fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, origin, true, &remaining, fill_margin, remaining_polygons, iteration, glue_box);
|
||||
fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration, glue_box);
|
||||
|
||||
new_fill_region.swap (remaining);
|
||||
fill_region = &new_fill_region;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,6 @@ fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell
|
|||
DB_PUBLIC void
|
||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
||||
const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Point &origin = db::Point (), const db::Box &glue_box = db::Box ());
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Box &glue_box = db::Box ());
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,14 @@ struct layer
|
|||
operator= (d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The move constructor
|
||||
*/
|
||||
layer (const layer &&d)
|
||||
{
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The assignment operator
|
||||
*
|
||||
|
|
@ -123,6 +131,20 @@ struct layer
|
|||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The assignment operator (move semantics)
|
||||
*/
|
||||
layer &operator= (const layer &&d)
|
||||
{
|
||||
if (&d != this) {
|
||||
m_box_tree = d.m_box_tree;
|
||||
m_bbox = d.m_bbox;
|
||||
m_bbox_dirty = d.m_bbox_dirty;
|
||||
m_tree_dirty = d.m_tree_dirty;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the iterator for an object given by a pointer
|
||||
*/
|
||||
|
|
@ -207,6 +229,18 @@ struct layer
|
|||
return m_box_tree.insert (sh);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a new shape object (move semantics)
|
||||
*/
|
||||
iterator insert (const Sh &&sh)
|
||||
{
|
||||
// inserting will make the bbox and the tree "dirty" - i.e.
|
||||
// it will need to be updated.
|
||||
m_bbox_dirty = true;
|
||||
m_tree_dirty = true;
|
||||
return m_box_tree.insert (sh);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replace the given element with a new one
|
||||
*
|
||||
|
|
@ -228,6 +262,19 @@ struct layer
|
|||
return *ncpos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replace the given element with a new one (move semantics)
|
||||
*/
|
||||
Sh &replace (iterator pos, const Sh &&sh)
|
||||
{
|
||||
m_bbox_dirty = true;
|
||||
m_tree_dirty = true;
|
||||
non_const_iterator ncpos;
|
||||
to_non_const_box_tree_iter (pos, ncpos, StableTag ());
|
||||
*ncpos = sh;
|
||||
return *ncpos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erasing of an element
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1626,7 +1626,7 @@ AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, const db::Vecto
|
|||
m_ny = ny;
|
||||
|
||||
if (mp_av) {
|
||||
delete mp_av;
|
||||
delete[] mp_av;
|
||||
}
|
||||
|
||||
mp_av = new area_type [nx * ny];
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ public:
|
|||
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
||||
|
||||
virtual const TransformationReducer *vars () const { return 0; }
|
||||
virtual bool result_is_merged () const { return true; } // we believe so ...
|
||||
virtual bool result_is_merged () const { return false; } // isn't merged for nested holes :(
|
||||
virtual bool requires_raw_input () const { return false; }
|
||||
virtual bool wants_variants () const { return true; }
|
||||
virtual bool result_must_not_be_merged () const { return false; }
|
||||
|
|
@ -577,7 +577,7 @@ public:
|
|||
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
||||
|
||||
virtual const TransformationReducer *vars () const { return 0; }
|
||||
virtual bool result_is_merged () const { return true; } // we believe so ...
|
||||
virtual bool result_is_merged () const { return false; } // isn't merged for nested hulls :(
|
||||
virtual bool requires_raw_input () const { return false; }
|
||||
virtual bool wants_variants () const { return true; }
|
||||
virtual bool result_must_not_be_merged () const { return false; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -219,6 +231,20 @@ public:
|
|||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1312,9 +1312,9 @@ fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill
|
|||
|
||||
static void
|
||||
fill_region_multi (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
||||
{
|
||||
db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box);
|
||||
db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
|
||||
}
|
||||
|
||||
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
|
||||
|
|
@ -1881,7 +1881,6 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
gsi::arg ("column_step"),
|
||||
gsi::arg ("fill_margin", db::Vector ()),
|
||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||
gsi::arg ("origin", db::Point ()),
|
||||
gsi::arg ("glue_box", db::Box ()),
|
||||
"@brief Fills the given region with cells of the given type in enhanced mode with iterations\n"
|
||||
"This version operates like \\fill_region, but repeats the fill generation until no further fill cells can be placed. "
|
||||
|
|
|
|||
|
|
@ -730,9 +730,9 @@ fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill
|
|||
|
||||
static void
|
||||
fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
|
||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
||||
{
|
||||
db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box);
|
||||
db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
|
||||
}
|
||||
|
||||
static db::Point default_origin;
|
||||
|
|
@ -2921,7 +2921,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
gsi::arg ("column_step"),
|
||||
gsi::arg ("fill_margin", db::Vector ()),
|
||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||
gsi::arg ("origin", db::Point ()),
|
||||
gsi::arg ("glue_box", db::Box ()),
|
||||
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ void run_test1 (tl::TestBase *_this, bool deep)
|
|||
unsigned int l1002 = ly.get_layer (db::LayerProperties (1002, 0));
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l1002);
|
||||
|
||||
primary = new db::CompoundRegionOperationPrimaryNode ();
|
||||
db::CompoundRegionCheckOperationNode space_check (primary, db::SpaceRelation, false /*==all polygons*/, 1050, check_options);
|
||||
|
||||
res = r.cop_to_edge_pairs (space_check);
|
||||
|
|
|
|||
|
|
@ -30,44 +30,73 @@ TEST(1)
|
|||
{
|
||||
db::D25TechnologyComponent comp;
|
||||
|
||||
comp.compile_from_source ("1/0: 1.0 1.5 # a comment");
|
||||
comp.set_src ("1/0: 1.0 1.5 # a comment");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
|
||||
|
||||
comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5");
|
||||
comp.set_src ("1/0: zstart=1.0 zstop=1.5");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
|
||||
|
||||
comp.compile_from_source ("1/0: zstart=1.0 height=0.5");
|
||||
comp.set_src ("1/0: zstart=1.0 height=0.5");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
|
||||
|
||||
comp.compile_from_source ("1/0: 1.0 height=0.5");
|
||||
comp.set_src ("1/0: 1.0 height=0.5");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
|
||||
|
||||
comp.compile_from_source ("1/0: zstop=1.5 height=0.5");
|
||||
comp.set_src ("1/0: zstop=1.5 height=0.5");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
|
||||
|
||||
comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5\nname: height=3");
|
||||
comp.set_src ("1/0: zstart=1.0 zstop=1.5\nname: height=3");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=1.5, zstop=4.5");
|
||||
|
||||
comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5\nname: zstart=4.0 height=3\n\n# a comment line");
|
||||
comp.set_src ("1/0: zstart=1.0 zstop=1.5\nname: zstart=4.0 height=3\n\n# a comment line");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
|
||||
|
||||
comp.set_src ("var x=1.0\n1/0: zstart=x zstop=x+0.5\nname: zstart=4.0 height=3\n\n# a comment line");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
|
||||
|
||||
comp.set_src ("var x=1.0\nif x == 1.0\n1/0: zstart=x zstop=x+0.5\nelse\n1/0: zstart=0 zstop=0\nend\nname: zstart=4.0 height=3\n\n# a comment line");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
|
||||
|
||||
comp.set_src ("var x=2.0\nif x == 1.0\n1/0: zstart=x zstop=x+0.5\nelse\n1/0: zstart=0 zstop=0\nend\nname: zstart=4.0 height=3\n\n# a comment line");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (comp.to_string (), "1/0: zstart=0, zstop=0\nname: zstart=4, zstop=7");
|
||||
|
||||
try {
|
||||
comp.compile_from_source ("blabla");
|
||||
comp.set_src ("blabla");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (false, true);
|
||||
} catch (...) { }
|
||||
|
||||
try {
|
||||
comp.compile_from_source ("1/0: 1 2 3");
|
||||
comp.set_src ("1/0: 1 2 3");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (false, true);
|
||||
} catch (...) { }
|
||||
|
||||
try {
|
||||
comp.compile_from_source ("1/0: foo=1 bar=2");
|
||||
comp.set_src ("1/0: foo=1 bar=2");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (false, true);
|
||||
} catch (...) { }
|
||||
|
||||
try {
|
||||
comp.compile_from_source ("1/0: 1;2");
|
||||
comp.set_src ("1/0: 1;*2");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (false, true);
|
||||
} catch (...) { }
|
||||
|
||||
try {
|
||||
comp.set_src ("error 42");
|
||||
comp.compile_from_source ();
|
||||
EXPECT_EQ (false, true);
|
||||
} catch (...) { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -694,8 +694,8 @@ TEST(10_HullsAndHoles)
|
|||
|
||||
db::Region hulls = r1_sized.hulls ();
|
||||
db::Region holes = r1_sized.holes ();
|
||||
EXPECT_EQ (hulls.is_merged (), true);
|
||||
EXPECT_EQ (holes.is_merged (), true);
|
||||
EXPECT_EQ (hulls.is_merged (), false);
|
||||
EXPECT_EQ (holes.is_merged (), false);
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
|
|
|||
|
|
@ -259,6 +259,10 @@ module DRC
|
|||
DRCFillOrigin::new
|
||||
end
|
||||
|
||||
def multi_origin
|
||||
DRCFillOrigin::new(nil, nil, true)
|
||||
end
|
||||
|
||||
def origin(x, y)
|
||||
DRCFillOrigin::new(x, y)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4251,7 +4251,9 @@ CODE
|
|||
# @li @b origin(x, y) @/b: specifies a fixed point to align the pattern with. This point specifies the location
|
||||
# of the reference point for one pattern cell. @/li
|
||||
# @li @b auto_origin @/b: lets the algorithm choose the origin. This may result is a slightly better fill coverage
|
||||
# as the algorithm is able to determine a pattern origin per fill island. @/li
|
||||
# as the algorithm is able to determine a pattern origin per island to fill. @/li
|
||||
# @li @b multi_origin @/b: lets the algorithm choose the origin and repeats the fill with different origins
|
||||
# until no further fill cell can be fitted. @/li
|
||||
# @li @b fill_pattern(..) @/b: specifies the fill pattern. @/li
|
||||
# @/ul
|
||||
#
|
||||
|
|
@ -4355,6 +4357,7 @@ CODE
|
|||
column_step = nil
|
||||
pattern = nil
|
||||
origin = RBA::DPoint::new
|
||||
repeat = false
|
||||
|
||||
args.each_with_index do |a,ai|
|
||||
if a.is_a?(DRCSource)
|
||||
|
|
@ -4381,6 +4384,7 @@ CODE
|
|||
end
|
||||
elsif a.is_a?(DRCFillOrigin)
|
||||
origin = a.origin
|
||||
repeat = a.repeat
|
||||
else
|
||||
raise("Argument ##{ai+1} not understood for '#{m}'")
|
||||
end
|
||||
|
|
@ -4435,31 +4439,22 @@ CODE
|
|||
tp.var("cs", cs)
|
||||
tp.var("origin", origin)
|
||||
tp.var("fc_index", fc_index)
|
||||
tp.var("repeat", repeat)
|
||||
tp.var("with_left", with_left)
|
||||
|
||||
if with_left
|
||||
tp.queue(<<"END")
|
||||
var tc_box = _frame.bbox;
|
||||
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
||||
!tile_box.empty && (
|
||||
tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height)));
|
||||
tile_box = tile_box & tc_box;
|
||||
var left = Region.new;
|
||||
tp.queue(<<"END")
|
||||
var tc_box = _frame.bbox;
|
||||
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
||||
!tile_box.empty && (
|
||||
tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height)));
|
||||
tile_box = tile_box & tc_box;
|
||||
var left = with_left ? Region.new : nil;
|
||||
repeat ?
|
||||
(region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, Vector.new, left, _tile.bbox) :
|
||||
(region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, Vector.new, left, _tile.bbox);
|
||||
_output(#{result_arg}, left)
|
||||
)
|
||||
with_left && _output(#{result_arg}, left)
|
||||
)
|
||||
END
|
||||
else
|
||||
tp.queue(<<"END")
|
||||
var tc_box = _frame.bbox;
|
||||
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
||||
!tile_box.empty && (
|
||||
tile_box.right = tile_box.right + rs.x - 1;
|
||||
tile_box.top = tile_box.top + cs.y - 1;
|
||||
tile_box = tile_box & tc_box;
|
||||
(region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, nil, Vector.new, nil, _tile.bbox)
|
||||
)
|
||||
END
|
||||
end
|
||||
|
||||
begin
|
||||
@engine._output_layout.start_changes
|
||||
|
|
@ -4477,10 +4472,19 @@ END
|
|||
end
|
||||
|
||||
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
|
||||
self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result)
|
||||
if repeat
|
||||
self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, RBA::Vector::new, result)
|
||||
else
|
||||
self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if fill_cell.parent_cells == 0
|
||||
# fill cell not required (not placed) -> remove
|
||||
fill_cell.delete
|
||||
end
|
||||
|
||||
self.data.disable_progress
|
||||
|
||||
|
|
|
|||
|
|
@ -334,7 +334,8 @@ module DRC
|
|||
|
||||
# A wrapper for the fill origin definition
|
||||
class DRCFillOrigin
|
||||
def initialize(x = nil, y = nil)
|
||||
def initialize(x = nil, y = nil, repeat = false)
|
||||
@repeat = repeat
|
||||
if !x && !y
|
||||
@origin = nil
|
||||
else
|
||||
|
|
@ -350,6 +351,9 @@ module DRC
|
|||
def origin
|
||||
@origin
|
||||
end
|
||||
def repeat
|
||||
@repeat
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the tile_size option
|
||||
|
|
|
|||
|
|
@ -1222,3 +1222,13 @@ TEST(45_fillWithOverlappingBoxesTiled)
|
|||
{
|
||||
run_test (_this, "45", false);
|
||||
}
|
||||
|
||||
TEST(46_fillWithOverlappingBoxes)
|
||||
{
|
||||
run_test (_this, "46", false);
|
||||
}
|
||||
|
||||
TEST(47_fillWithOverlappingBoxesTiled)
|
||||
{
|
||||
run_test (_this, "47", false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -542,6 +542,9 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (rows_le->text ()), rows);
|
||||
if (rows < 1) {
|
||||
throw tl::Exception (tl::to_string (tr ("Rows count can't be zero")));
|
||||
}
|
||||
lay::indicate_error (rows_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (rows_le, &ex);
|
||||
|
|
@ -550,6 +553,9 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
|
|||
|
||||
try {
|
||||
tl::from_string (tl::to_string (columns_le->text ()), cols);
|
||||
if (cols < 1) {
|
||||
throw tl::Exception (tl::to_string (tr ("Columns count can't be zero")));
|
||||
}
|
||||
lay::indicate_error (columns_le, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (columns_le, &ex);
|
||||
|
|
|
|||
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
|
||||
of the reference point for one pattern cell. </li>
|
||||
<li><b>auto_origin </b>: lets the algorithm choose the origin. This may result is a slightly better fill coverage
|
||||
as the algorithm is able to determine a pattern origin per fill island. </li>
|
||||
as the algorithm is able to determine a pattern origin per island to fill. </li>
|
||||
<li><b>multi_origin </b>: lets the algorithm choose the origin and repeats the fill with different origins
|
||||
until no further fill cell can be fitted. </li>
|
||||
<li><b>fill_pattern(..) </b>: specifies the fill pattern. </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<topic href="/about/variant_notation.xml"/>
|
||||
<topic href="/about/lef_def_import.xml"/>
|
||||
<topic href="/about/connectivity.xml"/>
|
||||
<topic href="/about/25d_view.xml"/>
|
||||
<topic href="/about/symbolic_layers.xml"/>
|
||||
<topic href="/about/layer_sources.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_netter.xml">doc/about/lvs_ref_netter.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 prefix="/help/manual">
|
||||
<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 ()) {
|
||||
current_view ()->menu_activated (symbol);
|
||||
} 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>
|
||||
</font>
|
||||
</property>
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ AnnotationShapes::AnnotationShapes (const AnnotationShapes &d)
|
|||
operator= (d);
|
||||
}
|
||||
|
||||
AnnotationShapes::AnnotationShapes (const AnnotationShapes &&d)
|
||||
: db::LayoutStateModel (true /*busy*/), db::Object (d)
|
||||
{
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
AnnotationShapes::~AnnotationShapes ()
|
||||
{
|
||||
clear ();
|
||||
|
|
@ -106,7 +112,21 @@ AnnotationShapes::operator= (const AnnotationShapes &d)
|
|||
}
|
||||
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 ()
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
|
|
@ -126,7 +146,17 @@ AnnotationShapes::insert (const shape_type &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)
|
||||
{
|
||||
m_layer.reserve (n);
|
||||
|
|
@ -156,7 +186,21 @@ AnnotationShapes::replace (iterator pos, const shape_type &sh)
|
|||
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)
|
||||
{
|
||||
AnnotationLayerOp *layop = dynamic_cast<AnnotationLayerOp *> (op);
|
||||
|
|
|
|||
|
|
@ -135,16 +135,37 @@ public:
|
|||
*/
|
||||
AnnotationShapes (const AnnotationShapes &d);
|
||||
|
||||
/**
|
||||
* @brief Copy ctor
|
||||
*/
|
||||
AnnotationShapes (const AnnotationShapes &&d);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
*/
|
||||
AnnotationShapes &operator= (const AnnotationShapes &d);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator (move)
|
||||
*/
|
||||
AnnotationShapes &operator= (const AnnotationShapes &&d);
|
||||
|
||||
/**
|
||||
* @brief Insert a shape_type
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
|
@ -212,6 +233,11 @@ public:
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ BookmarkItem::to_string () const
|
|||
BrowserPanel::BrowserPanel (QWidget *parent)
|
||||
: QWidget (parent),
|
||||
m_back_dm (this, &BrowserPanel::back),
|
||||
m_new_url_dm (this, &BrowserPanel::new_url),
|
||||
mp_dispatcher (0)
|
||||
{
|
||||
init ();
|
||||
|
|
@ -125,6 +126,7 @@ BrowserPanel::init ()
|
|||
|
||||
mp_ui->browser->addAction (mp_ui->action_find);
|
||||
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->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 (returnPressed ()), 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 (forwardAvailable (bool)), mp_ui->forward_pb, SLOT (setEnabled (bool)));
|
||||
connect (mp_ui->outline_tree, SIGNAL (itemActivated (QTreeWidgetItem *, int)), this, SLOT (outline_item_clicked (QTreeWidgetItem *)));
|
||||
|
|
@ -218,7 +221,7 @@ BrowserPanel::title () const
|
|||
std::string
|
||||
BrowserPanel::url () const
|
||||
{
|
||||
return m_cached_url;
|
||||
return tl::to_string (mp_ui->browser->source ().toString ());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -416,13 +419,24 @@ BrowserPanel::search_text_changed (const QString &text)
|
|||
}
|
||||
|
||||
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);
|
||||
if (title != m_current_title) {
|
||||
m_current_title = title;
|
||||
emit title_changed (title);
|
||||
}
|
||||
m_current_title = title;
|
||||
emit title_changed (title);
|
||||
|
||||
// refresh on-page search
|
||||
page_search_edited ();
|
||||
|
|
|
|||
|
|
@ -441,7 +441,9 @@ protected slots:
|
|||
void page_search_next();
|
||||
void search_text_changed(const QString &text);
|
||||
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 bookmark_item_selected (QTreeWidgetItem *item);
|
||||
void delete_bookmark ();
|
||||
|
|
@ -462,6 +464,7 @@ private:
|
|||
Ui::BrowserPanel *mp_ui;
|
||||
bool m_schedule_back;
|
||||
tl::DeferredMethod<BrowserPanel> m_back_dm;
|
||||
tl::DeferredMethod<BrowserPanel> m_new_url_dm;
|
||||
std::string m_search_url, m_search_query_item;
|
||||
QString m_current_title;
|
||||
QList<QTextEdit::ExtraSelection> m_search_selection;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,13 @@ D25TechnologyComponentEditor::commit ()
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1027,6 +1027,8 @@ NetlistBrowserPage::adjust_view ()
|
|||
ebox += bbox_for_device_abstract (layout, a->device_abstract, a->trans);
|
||||
}
|
||||
|
||||
trans *= device->trans ();
|
||||
|
||||
} else if (net) {
|
||||
|
||||
db::cell_index_type cell_index = net->circuit ()->cell_index ();
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ PropertiesDialog::apply ()
|
|||
{
|
||||
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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,35 @@
|
|||
|
||||
<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>
|
||||
|
||||
<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="Apostrophed String"/>
|
||||
<DetectChar attribute="Comment" char="#" context="Comment"/>
|
||||
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
|
||||
|
||||
<RegExpr attribute="Normal" String=":" context="After LD"/>
|
||||
|
||||
|
|
@ -22,22 +44,52 @@
|
|||
<DetectChar attribute="Normal" char="/" context="#stay"/>
|
||||
<RegExpr attribute="Raw String" String="[_a-zA-Z]\w*" context="#stay"/>
|
||||
|
||||
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
|
||||
|
||||
</context>
|
||||
|
||||
<context name="Comment" attribute="Comment" lineEndContext="Normal">
|
||||
</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"/>
|
||||
</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"/>
|
||||
|
||||
<DetectChar attribute="Normal" char="," context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="=" context="#stay"/>
|
||||
<StringDetect attribute="Symbol" String="zstart" context="#stay"/>
|
||||
<StringDetect attribute="Symbol" String="zstop" context="#stay"/>
|
||||
<StringDetect attribute="Symbol" String="height" context="#stay"/>
|
||||
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
|
||||
<DetectChar attribute="Normal" char="(" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char=")" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="[" context="#stay"/>
|
||||
<DetectChar attribute="Normal" char="]" context="#stay"/>
|
||||
|
||||
<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 name="Error" attribute="Error" lineEndContext="Normal">
|
||||
|
|
@ -46,19 +98,21 @@
|
|||
<context name="Quoted String" attribute="String" lineEndContext="Error">
|
||||
<StringDetect 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 name="Apostrophed String" attribute="Raw String" lineEndContext="Error">
|
||||
<StringDetect 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>
|
||||
|
||||
</contexts>
|
||||
|
||||
<itemDatas>
|
||||
|
||||
<itemData name="Normal Text" defStyleNum="dsNormal"/>
|
||||
<itemData name="Name" defStyleNum="dsNormal"/>
|
||||
|
||||
<itemData name="Comment" defStyleNum="dsComment"/>
|
||||
<itemData name="Float" defStyleNum="dsFloat"/>
|
||||
|
|
@ -73,4 +127,12 @@
|
|||
</itemDatas>
|
||||
|
||||
</highlighting>
|
||||
|
||||
<general>
|
||||
<comments>
|
||||
<comment name="singleLine" start="#"/>
|
||||
</comments>
|
||||
<keywords casesensitive="1" weakDeliminator="!?"/>
|
||||
</general>
|
||||
|
||||
</language>
|
||||
|
|
|
|||
|
|
@ -206,7 +206,13 @@ GDS2Reader::get_string ()
|
|||
void
|
||||
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
|
||||
|
|
|
|||
|
|
@ -350,9 +350,9 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="doc_label">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ D25Camera::~D25Camera ()
|
|||
void
|
||||
D25Camera::init ()
|
||||
{
|
||||
m_fov = 90.0;
|
||||
m_fov = 45.0;
|
||||
m_cam_azimuth = m_cam_elevation = 0.0;
|
||||
m_top_view = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public:
|
|||
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||
{
|
||||
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*/)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "layD25View.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "layQtTools.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 ()));
|
||||
|
||||
mp_ui->gl_stack->setCurrentIndex (0);
|
||||
|
||||
lay::activate_help_links (mp_ui->doc_label);
|
||||
}
|
||||
|
||||
D25View::~D25View ()
|
||||
|
|
|
|||
|
|
@ -246,40 +246,23 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
|||
|
||||
} else {
|
||||
|
||||
// compute vector of line of sight
|
||||
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);
|
||||
double d = event->angleDelta ().y () * (1.0 / (90 * 16));
|
||||
|
||||
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));
|
||||
m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second;
|
||||
QMatrix4x4 t;
|
||||
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 {
|
||||
|
||||
// "Ctrl" is zoom
|
||||
|
||||
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
|
||||
|
||||
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);
|
||||
m_scale_factor *= exp (d);
|
||||
|
||||
emit scale_factor_changed (m_scale_factor);
|
||||
|
||||
|
|
@ -294,8 +277,65 @@ void
|
|||
D25ViewWidget::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
if (event->key () == Qt::Key_Shift) {
|
||||
|
||||
mp_mode.reset (0);
|
||||
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)
|
||||
{
|
||||
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 ()) {
|
||||
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 ()) {
|
||||
return l->second;
|
||||
return &l->second;
|
||||
} else {
|
||||
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;
|
||||
|
||||
|
|
@ -457,16 +497,18 @@ namespace {
|
|||
|
||||
if (comp) {
|
||||
|
||||
std::map<db::LayerProperties, const 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-> ()));
|
||||
std::map<db::LayerProperties, db::D25LayerInfo, db::LPLogicalLessFunc> zi_by_lp;
|
||||
|
||||
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 ();
|
||||
for (int l = 0; l < int (ly.layers ()); ++l) {
|
||||
if (ly.is_valid_layer (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 possible, try by name only
|
||||
z = zi_by_lp.find (db::LayerProperties (lp.name));
|
||||
|
|
@ -485,7 +527,7 @@ namespace {
|
|||
|
||||
|
||||
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.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.draw_to (this, positions, GL_TRIANGLES);
|
||||
vertexes.draw_to (this, positions, GL_LINES);
|
||||
|
||||
// draw base plane
|
||||
|
||||
|
|
@ -1029,8 +1074,8 @@ D25ViewWidget::paintGL ()
|
|||
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
|
||||
int cube_size = 64;
|
||||
int cube_margin = 20;
|
||||
int cube_size = 32;
|
||||
int cube_margin = 40;
|
||||
|
||||
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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -562,6 +575,20 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ public:
|
|||
*/
|
||||
explicit vector (const tl::vector<T> &d) : base (d) { }
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
explicit vector (const tl::vector<T> &&d) : base (d) { }
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
|
|
@ -71,6 +76,17 @@ public:
|
|||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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