Merge branch 'bugfixes' into issue-757

This commit is contained in:
Matthias Koefferlein 2021-04-11 09:10:38 +02:00
commit 841e6c8726
53 changed files with 1173 additions and 220 deletions

279
Changelog
View File

@ -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

View File

@ -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 ();
}

View File

@ -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);
}

View File

@ -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
*/

View File

@ -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

View File

@ -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")
);
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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 ());
}

View File

@ -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
*

View File

@ -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];

View File

@ -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; }

View File

@ -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
*/

View File

@ -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. "

View File

@ -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"

View File

@ -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);

View File

@ -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 (...) { }
}

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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"/>

View File

@ -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>

View 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")));
}
}

View File

@ -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>

View File

@ -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);

View File

@ -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
*

View File

@ -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 ();

View File

@ -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;

View File

@ -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

View File

@ -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 ();

View File

@ -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 {

View File

@ -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="&quot;" 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="&quot;" 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="[\^\*\.\+\-%/!=&lt;&gt;&amp;|,\?:]" 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="\\\&quot;" context="#stay"/>
<DetectChar char="&quot;" attribute="String" context="Normal"/>
<DetectChar char="&quot;" 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>

View File

@ -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

View File

@ -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 (&lt;a href=&quot;int:/about/25d_view.xml&quot;&gt;more&lt;/a&gt;)</string>
</property>
</widget>
</item>

View File

@ -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;
}

View File

@ -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*/)

View File

@ -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 ()

View File

@ -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));

View File

@ -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
*

View File

@ -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
*/

25
testdata/drc/drcSimpleTests_46.drc vendored Normal file
View File

@ -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)

BIN
testdata/drc/drcSimpleTests_46.gds vendored Normal file

Binary file not shown.

27
testdata/drc/drcSimpleTests_47.drc vendored Normal file
View File

@ -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)

BIN
testdata/drc/drcSimpleTests_47.gds vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au46.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au47.gds vendored Normal file

Binary file not shown.