diff --git a/src/db/db/dbLayerProperties.cc b/src/db/db/dbLayerProperties.cc
index 4252ed361..bced3f25e 100644
--- a/src/db/db/dbLayerProperties.cc
+++ b/src/db/db/dbLayerProperties.cc
@@ -22,6 +22,7 @@
#include "dbLayerProperties.h"
+#include "dbStreamLayers.h"
namespace db
{
@@ -30,7 +31,7 @@ namespace db
// Implementation of the LayerProperties class
LayerProperties::LayerProperties ()
- : name (), layer (-1), datatype (-1)
+ : name (), layer (db::any_ld ()), datatype (db::any_ld ())
{ }
LayerProperties::LayerProperties (int l, int d)
@@ -38,7 +39,7 @@ LayerProperties::LayerProperties (int l, int d)
{ }
LayerProperties::LayerProperties (const std::string &n)
- : name (n), layer (-1), datatype (-1)
+ : name (n), layer (db::any_ld ()), datatype (db::any_ld ())
{ }
LayerProperties::LayerProperties (int l, int d, const std::string &n)
@@ -48,7 +49,13 @@ LayerProperties::LayerProperties (int l, int d, const std::string &n)
bool
LayerProperties::is_named () const
{
- return (layer < 0 || datatype < 0) && ! name.empty ();
+ return db::is_any_ld (layer) && db::is_any_ld (datatype) && ! name.empty ();
+}
+
+bool
+LayerProperties::is_null () const
+{
+ return db::is_any_ld (layer) && db::is_any_ld (datatype) && name.empty ();
}
bool
@@ -122,34 +129,79 @@ LayerProperties::operator< (const LayerProperties &b) const
return name < b.name;
}
+static std::string format_ld (db::ld_type ld)
+{
+ if (db::is_static_ld (ld)) {
+ return tl::to_string (ld);
+ } else if (db::is_any_ld (ld)) {
+ return "*";
+ } else if (db::is_relative_ld (ld)) {
+ db::ld_type offset = db::ld_offset (ld);
+ if (offset < 0) {
+ return "*-" + tl::to_string (-offset);
+ } else {
+ return "*+" + tl::to_string (offset);
+ }
+ } else {
+ return tl::to_string (ld);
+ }
+}
+
std::string
-LayerProperties::to_string () const
+LayerProperties::to_string (bool as_target) const
{
std::string r;
if (! name.empty ()) {
if (is_named ()) {
r = tl::to_word_or_quoted_string (name);
} else {
- r = tl::to_word_or_quoted_string (name) + tl::sprintf (" (%d/%d)", layer, datatype);
+ r = tl::to_word_or_quoted_string (name) + " (" + format_ld (layer) + "/" + format_ld (datatype) + ")";
}
- } else if (! is_null ()) {
- r = tl::sprintf ("%d/%d", layer, datatype);
+ } else if (! is_null () || as_target) {
+ r = format_ld (layer) + "/" + format_ld (datatype);
}
return r;
}
-void
-LayerProperties::read (tl::Extractor &ex)
+static bool read_ld (tl::Extractor &ex, ld_type &l, bool with_relative)
{
- layer = -1;
- datatype = -1;
+ if (ex.test ("*")) {
+
+ int offset = 0;
+
+ tl::Extractor eex = ex;
+ if (with_relative && eex.test ("+") && eex.try_read (offset)) {
+ l = db::relative_ld (offset);
+ ex = eex;
+ } else {
+ eex = ex;
+ if (with_relative && eex.test ("-") && eex.try_read (offset)) {
+ l = db::relative_ld (-offset);
+ ex = eex;
+ } else {
+ l = db::any_ld ();
+ }
+ }
+
+ return true;
+
+ } else {
+ return ex.try_read (l);
+ }
+}
+
+void
+LayerProperties::read (tl::Extractor &ex, bool as_target)
+{
+ layer = db::any_ld ();
+ datatype = db::any_ld ();
name.clear ();
int l = 0, d = 0;
- if (ex.try_read (l)) {
+ if (read_ld (ex, l, as_target)) {
if (ex.test ("/")) {
- ex.read (d);
+ read_ld (ex, d, as_target);
}
layer = l;
@@ -159,10 +211,11 @@ LayerProperties::read (tl::Extractor &ex)
if (ex.test ("(")) {
- ex.read (l);
+ read_ld (ex, l, as_target);
if (ex.test ("/")) {
- ex.read (d);
+ read_ld (ex, d, as_target);
}
+
ex.expect (")");
layer = l;
diff --git a/src/db/db/dbLayerProperties.h b/src/db/db/dbLayerProperties.h
index 56022a985..b08e33712 100644
--- a/src/db/db/dbLayerProperties.h
+++ b/src/db/db/dbLayerProperties.h
@@ -39,6 +39,10 @@ namespace db
*
* The layer properties are basically to be used for storing of layer name and
* layer/datatype information.
+ *
+ * A special use case is for the target of a layer mapping specification.
+ * In this case, the layer properties can make use of the relative
+ * layer/datatype specifications.
*/
struct DB_PUBLIC LayerProperties
{
@@ -68,10 +72,7 @@ struct DB_PUBLIC LayerProperties
* A null specification is one created by the default constructor. It does not have
* a layer, datatype or name assigned.
*/
- bool is_null () const
- {
- return layer < 0 && datatype < 0 && name.empty ();
- }
+ bool is_null () const;
/**
* @brief Return true, if the layer is specified by name only
@@ -81,12 +82,17 @@ struct DB_PUBLIC LayerProperties
/**
* @brief Convert to a string
*/
- std::string to_string () const;
+ std::string to_string (bool as_target = false) const;
/**
* @brief Extract from a tl::Extractor
+ *
+ * With "with_relative" true, the extractor allows giving
+ * relative layer/datatype specifications in the format "*+1" or "*-100".
+ * "*" for layer or datatype is for "don't care" (on input) or "leave as is"
+ * (for output).
*/
- void read (tl::Extractor &ex);
+ void read (tl::Extractor &ex, bool as_target = false);
/**
* @brief "Logical" equality
diff --git a/src/db/db/dbNamedLayerReader.cc b/src/db/db/dbNamedLayerReader.cc
index 53cdef1ff..497fad153 100644
--- a/src/db/db/dbNamedLayerReader.cc
+++ b/src/db/db/dbNamedLayerReader.cc
@@ -128,7 +128,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
std::pair ll (false, 0);
- ll = m_layer_map.logical (n);
+ ll = m_layer_map.logical (n, layout);
if (! ll.first && !m_keep_layer_names) {
if (extract_plain_layer (n.c_str (), l)) {
@@ -136,7 +136,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
db::LayerProperties lp;
lp.layer = l;
lp.datatype = 0;
- ll = m_layer_map.logical (lp);
+ ll = m_layer_map.logical (lp, layout);
} else if (extract_ld (n.c_str (), l, d, on)) {
@@ -144,7 +144,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
lp.layer = l;
lp.datatype = d;
lp.name = on;
- ll = m_layer_map.logical (lp);
+ ll = m_layer_map.logical (lp, layout);
}
diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc
index f664265d0..37c4dfcce 100644
--- a/src/db/db/dbStreamLayers.cc
+++ b/src/db/db/dbStreamLayers.cc
@@ -71,13 +71,31 @@ LayerMap::LayerMap ()
// .. nothing yet ..
}
-std::pair
+std::pair
LayerMap::logical (const LDPair &p) const
+{
+ return logical_internal (p, false);
+}
+
+std::pair
+LayerMap::logical (const std::string &n) const
+{
+ return logical_internal (n, false);
+}
+
+std::pair
+LayerMap::logical (const db::LayerProperties &p) const
+{
+ return logical_internal (p, false);
+}
+
+std::pair
+LayerMap::logical_internal (const LDPair &p, bool allow_placeholder) const
{
const datatype_map *dm = m_ld_map.mapped (p.layer);
if (dm) {
const unsigned int *l = dm->mapped (p.datatype);
- if (l) {
+ if (l && (allow_placeholder || ! is_placeholder (*l))) {
return std::make_pair (true, *l);
}
}
@@ -85,10 +103,10 @@ LayerMap::logical (const LDPair &p) const
}
std::pair
-LayerMap::logical (const std::string &n) const
+LayerMap::logical_internal (const std::string &n, bool allow_placeholder) const
{
std::map::const_iterator m = m_name_map.find (n);
- if (m != m_name_map.end ()) {
+ if (m != m_name_map.end () && (allow_placeholder || ! is_placeholder (m->second))) {
return std::make_pair (true, m->second);
} else {
return std::make_pair (false, 0);
@@ -96,16 +114,16 @@ LayerMap::logical (const std::string &n) const
}
std::pair
-LayerMap::logical (const db::LayerProperties &p) const
+LayerMap::logical_internal (const db::LayerProperties &p, bool allow_placeholder) const
{
if (p.layer >= 0 && p.datatype >= 0) {
- std::pair m = logical (db::LDPair (p.layer, p.datatype));
+ std::pair m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
if (m.first) {
return m;
}
}
if (! p.name.empty ()) {
- std::pair m = logical (p.name);
+ std::pair m = logical_internal (p.name, allow_placeholder);
if (m.first) {
return m;
}
@@ -113,6 +131,60 @@ LayerMap::logical (const db::LayerProperties &p) const
return std::make_pair (false, 0);
}
+bool
+LayerMap::is_placeholder (unsigned int l) const
+{
+ return (m_placeholders.size () > std::numeric_limits::max () - l);
+}
+
+std::pair
+LayerMap::logical (const db::LayerProperties &p, db::Layout &layout) const
+{
+ std::pair l = logical_internal (p, true);
+ if (l.first && is_placeholder (l.second)) {
+ return const_cast (this)->substitute_placeholder (p, l.second, layout);
+ } else {
+ return l;
+ }
+}
+
+std::pair
+LayerMap::logical (const db::LDPair &p, db::Layout &layout) const
+{
+ std::pair l = logical_internal (p, true);
+ if (l.first && is_placeholder (l.second)) {
+ return const_cast (this)->substitute_placeholder (db::LayerProperties (p.layer, p.datatype), l.second, layout);
+ } else {
+ return l;
+ }
+}
+
+std::pair
+LayerMap::substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout)
+{
+ const db::LayerProperties &lp_ph = m_placeholders [std::numeric_limits::max () - ph];
+ db::LayerProperties lp_new = p;
+ lp_new.layer = db::ld_combine (p.layer, lp_ph.layer);
+ lp_new.datatype = db::ld_combine (p.datatype, lp_ph.datatype);
+
+ unsigned int l_new = layout.insert_layer (lp_new);
+ map (p, l_new, lp_new);
+ return std::make_pair (true, l_new);
+}
+
+static std::string format_interval (ld_type l1, ld_type l2)
+{
+ if (l1 == 0 && l2 == std::numeric_limits::max ()) {
+ return "*";
+ } else if (l2 == std::numeric_limits::max ()) {
+ return tl::to_string (l1) + "-*";
+ } else if (l1 + 1 < l2) {
+ return tl::to_string (l1) + "-" + tl::to_string (l2 - 1);
+ } else {
+ return tl::to_string (l1);
+ }
+}
+
std::string
LayerMap::mapping_str (unsigned int ll) const
{
@@ -135,21 +207,13 @@ LayerMap::mapping_str (unsigned int ll) const
}
f1 = false;
- s += tl::to_string (l->first.first);
- if (l->first.first < l->first.second - 1) {
- s += "-";
- s += tl::to_string (l->first.second - 1);
- }
+ s += format_interval (l->first.first, l->first.second);
s += "/";
}
f2 = false;
- s += tl::to_string (d->first.first);
- if (d->first.first < d->first.second - 1) {
- s += "-";
- s += tl::to_string (d->first.second - 1);
- }
+ s += format_interval (d->first.first, d->first.second);
}
@@ -173,7 +237,7 @@ LayerMap::mapping_str (unsigned int ll) const
std::map::const_iterator t = m_target_layers.find (ll);
if (t != m_target_layers.end ()) {
s += " : ";
- s += t->second.to_string ();
+ s += t->second.to_string (true);
}
return s;
@@ -182,6 +246,9 @@ LayerMap::mapping_str (unsigned int ll) const
void
LayerMap::prepare (db::Layout &layout)
{
+ m_placeholders.clear ();
+ unsigned int ph = std::numeric_limits::max ();
+
std::map real_layers;
std::set mapped_layers;
@@ -190,16 +257,33 @@ LayerMap::prepare (db::Layout &layout)
std::vector old_layers = get_layers ();
for (std::vector::const_iterator l = old_layers.begin (); l != old_layers.end (); ++l) {
+
if (layout.is_valid_layer (*l)) {
+
real_layers.insert (std::make_pair (*l, *l));
mapped_layers.insert (*l);
+
} else {
- std::pair lm = layer_mapping.map_layer (mapping (*l));
- if (lm.first) {
- real_layers.insert (std::make_pair (*l, lm.second));
- mapped_layers.insert (lm.second);
+
+ db::LayerProperties lp = mapping (*l);
+ if (lp.is_named () || (db::is_static_ld (lp.layer) && db::is_static_ld (lp.datatype))) {
+
+ std::pair lm = layer_mapping.map_layer (lp);
+ if (lm.first) {
+ real_layers.insert (std::make_pair (*l, lm.second));
+ mapped_layers.insert (lm.second);
+ }
+
+ } else {
+
+ // install a placeholder index
+ m_placeholders.push_back (lp);
+ real_layers.insert (std::make_pair (*l, ph--));
+
}
+
}
+
}
// Now remap the indexes
@@ -253,10 +337,29 @@ LayerMap::mapping (unsigned int ll) const
std::map::const_iterator t = m_target_layers.find (ll);
if (t != m_target_layers.end ()) {
- p = t->second;
- }
- if (p.layer < 0 || p.datatype < 0) {
+ // a mapping is given. Use it.
+ p = t->second;
+
+ // special case: if it is a name mapping, add the layer mapping (for backward compatibility)
+ if (p.is_named ()) {
+
+ // no mapping is given. Use the lowest layer and datatype
+ for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
+ for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
+ if (d->second == ll) {
+ p.layer = l->first.first;
+ p.datatype = d->first.first;
+ break;
+ }
+ }
+ }
+
+ }
+
+ } else {
+
+ // no mapping is given. Use the lowest layer and datatype
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
if (d->second == ll) {
@@ -266,6 +369,7 @@ LayerMap::mapping (unsigned int ll) const
}
}
}
+
}
if (p.name.empty ()) {
@@ -284,19 +388,19 @@ LayerMap::mapping (unsigned int ll) const
void
LayerMap::map (const LDPair &p, unsigned int l)
{
- insert (p, p, l, LayerProperties ());
+ insert (p, p, l, (const LayerProperties *) 0);
}
void
LayerMap::map (const std::string &name, unsigned int l)
{
- insert (name, l, LayerProperties ());
+ insert (name, l, (const LayerProperties *) 0);
}
void
LayerMap::map (const LayerProperties &f, unsigned int l)
{
- if (f.layer >= 0 && f.datatype >= 0) {
+ if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
map (db::LDPair (f.layer, f.datatype), l);
}
if (! f.name.empty ()) {
@@ -307,19 +411,19 @@ LayerMap::map (const LayerProperties &f, unsigned int l)
void
LayerMap::map (const LDPair &p, unsigned int l, const LayerProperties &t)
{
- insert (p, p, l, t);
+ insert (p, p, l, &t);
}
void
LayerMap::map (const std::string &name, unsigned int l, const LayerProperties &t)
{
- insert (name, l, t);
+ insert (name, l, &t);
}
void
LayerMap::map (const LayerProperties &f, unsigned int l, const LayerProperties &t)
{
- if (f.layer >= 0 && f.datatype >= 0) {
+ if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
map (db::LDPair (f.layer, f.datatype), l, t);
}
if (! f.name.empty ()) {
@@ -330,13 +434,13 @@ LayerMap::map (const LayerProperties &f, unsigned int l, const LayerProperties &
void
LayerMap::map (const LDPair &p1, const LDPair &p2, unsigned int l)
{
- insert (p1, p2, l, LayerProperties ());
+ insert (p1, p2, l, (const LayerProperties *) 0);
}
void
LayerMap::map (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &lp)
{
- insert (p1, p2, l, lp);
+ insert (p1, p2, l, &lp);
}
/// Utility function for the expression parser:
@@ -346,11 +450,22 @@ parse_interval (tl::Extractor &ex, ld_interval &p)
{
ld_type n1 = 0, n2 = 0;
- ex.try_read (n1);
- if (ex.test ("-")) {
- ex.try_read (n2);
+ if (ex.test ("*")) {
+ n1 = 0;
+ // NOTE: as the upper limit is stored as n2 + 1, this will map to max():
+ n2 = std::numeric_limits::max () - 1;
} else {
- n2 = n1;
+ ex.try_read (n1);
+ if (ex.test ("-")) {
+ if (ex.test ("*")) {
+ // NOTE: as the upper limit is stored as n2 + 1, this will map to max():
+ n2 = std::numeric_limits::max () - 1;
+ } else {
+ ex.try_read (n2);
+ }
+ } else {
+ n2 = n1;
+ }
}
p.first = n1;
@@ -420,7 +535,7 @@ LayerMap::map_expr (tl::Extractor &ex, unsigned int l)
if (ex.test (":")) {
LayerProperties lp;
- lp.read (ex);
+ lp.read (ex, true);
m_target_layers[l] = lp;
}
@@ -434,10 +549,10 @@ LayerMap::map_expr (tl::Extractor &ex, unsigned int l)
}
void
-LayerMap::insert (const std::string &name, unsigned int l, const LayerProperties &target)
+LayerMap::insert (const std::string &name, unsigned int l, const LayerProperties *target)
{
- if (! (target == LayerProperties ())) {
- m_target_layers[l] = target;
+ if (target) {
+ m_target_layers[l] = *target;
}
m_name_map.insert (std::make_pair (name, l));
@@ -448,21 +563,29 @@ LayerMap::insert (const std::string &name, unsigned int l, const LayerProperties
}
void
-LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &target)
+LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties *target)
{
- if (! (target == LayerProperties ())) {
- m_target_layers[l] = target;
+ if (target) {
+ m_target_layers[l] = *target;
}
// create a single-interval list for the datatype range
LayerMap::datatype_map dt;
LmapJoinOp1 op1;
- dt.add (p1.datatype, p2.datatype + 1, l, op1);
+ if (db::is_static_ld (p1.datatype) && db::is_static_ld (p2.datatype)) {
+ dt.add (p1.datatype, p2.datatype + 1, l, op1);
+ } else {
+ dt.add (0, std::numeric_limits::max (), l, op1);
+ }
// add this to the layers using the special join operator that
// combines the datatype intervals
LmapJoinOp2 op2;
- m_ld_map.add (p1.layer, p2.layer + 1, dt, op2);
+ if (db::is_static_ld (p1.layer) && db::is_static_ld (p2.layer)) {
+ m_ld_map.add (p1.layer, p2.layer + 1, dt, op2);
+ } else {
+ m_ld_map.add (0, std::numeric_limits::max (), dt, op2);
+ }
if (l >= m_next_index) {
m_next_index = l + 1;
diff --git a/src/db/db/dbStreamLayers.h b/src/db/db/dbStreamLayers.h
index c9e048464..efc80b45b 100644
--- a/src/db/db/dbStreamLayers.h
+++ b/src/db/db/dbStreamLayers.h
@@ -34,6 +34,7 @@
#include "gsiObject.h"
#include
+ Wildcards
+
+
+ Source layers can be specified using wildcards. A wildcard is a "*" character
+ matching "any layer".
+ Examples for such expressions are:
+
+
+
+
+ | 10-*/0 |
+ Matching layer 10 and above, datatype 0 |
+
+
+ | */10 |
+ Matching datatype 10 of every layer |
+
+
+ | 0-5,10-*/* |
+ Matching layer 0 to 5 (inclusive) and above 10, all datatypes. |
+
+
+
+
+ When ranges or wildcards are used as match expressions, the specified
+ layers will be lumped together into a single layer. This layer will have
+ the least permitted layer and datatype number. For example, with a
+ match expression of "1-10/*", all these layers will be mapped to "1/0".
+ This behavior can be modified using a target layer specification with
+ wildcards.
+
+
+ Wildcard expansion and relative layer mapping
+
+
+ If the match expression includes a numerical range or wildcards
+ for the layer or datatype number, by default all these layers
+ will be combined into a single one, where it's layer or datatype number is derived
+ from the least permitted number.
+
+
+
+ This behavior can be modified using wildcard expansion. This is a target layer
+ which includes a "*" wildcard. This wildcard is substituted by the actual
+ layer or datatype number:
+
+
+
+
+ | 10-*/0 : */10 |
+ Maintain layers for layer 10 and above and map datatype to 10 |
+
+
+ | 10-*/0 : */* |
+ Select layers 10 and above, datatype 0 and maintain these as individual layers |
+
+
+ | 1/* : 2/* |
+ Map layer number 1 to 2, maintain all datatypes |
+
+
+
+
+ Relative layer mapping allows adding an offset to the layer or datatype numbers.
+ This offset can be negative with undefined behavior when the resulting number goes below
+ zero:
+
+
+
+
+ | 10-20/*: *+1000/* |
+ Selects all layers between 10 and 20, all datatypes. These layers will be
+ read into the original layers plus 1000 for the layer number. |
+
+
+ | 10/10-*: */*-10 |
+ Selects layer 10, datatypes 10 plus. The resulting datatypes will be 10 less starting from 0. |
+
+
+
diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
index bc496f762..85fe87027 100644
--- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
+++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
@@ -383,7 +383,7 @@ DXFReader::do_read (db::Layout &layout, db::cell_index_type top)
// create the zero layer - this is not mapped to GDS but can be specified in the layer mapping as
// a layer named "0".
- std::pair ll = layer_map ().logical (zero_layer_name);
+ std::pair ll = layer_map ().logical (zero_layer_name, layout);
if (ll.first) {
// create the layer if it is not part of the layout yet.
diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc
index 8006de403..4d6695891 100644
--- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc
+++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc
@@ -176,7 +176,7 @@ GDS2ReaderBase::finish_element (db::PropertiesRepository &rep)
std::pair
GDS2ReaderBase::open_dl (db::Layout &layout, const LDPair &dl, bool create)
{
- std::pair ll = m_layer_map.logical (dl);
+ std::pair ll = m_layer_map.logical (dl, layout);
if (ll.first) {
return ll;
diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
index 6b738f6bc..b1971b0e4 100644
--- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
+++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
@@ -391,3 +391,46 @@ TEST(Bug_121_2)
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}
+TEST(3_AdvancedMapping)
+{
+ db::Manager m (false);
+ db::Layout layout (&m);
+
+ db::LoadLayoutOptions options;
+ db::LayerMap lm, lm_read;
+
+ unsigned int n = 0;
+ lm.map_expr ("*/*: *+100/*", n++);
+ lm.map_expr ("1/*: */*", n++);
+ lm.map_expr ("1/10: 1/0", n++);
+ lm.map_expr ("1/20-30: 1/*+1000", n++);
+ lm.map_expr ("2/*", n++);
+ lm.map_expr ("2/10-20: */*", n++);
+ options.get_options ().layer_map = lm;
+
+ {
+ tl::InputStream file (tl::testsrc () + "/testdata/gds/alm.gds");
+ db::Reader reader (file);
+ lm_read = reader.read (layout, options);
+ }
+
+ EXPECT_EQ (lm_read.to_string_file_format (),
+ "1/10 : 1/0\n"
+ "2/0-9,21-*\n"
+ "1/0 : 1/0\n"
+ "1/1 : 1/1\n"
+ "1/20 : 1/1020\n"
+ "1/21 : 1/1021\n"
+ "2/10 : 2/10\n"
+ "2/11 : 2/11\n"
+ "42/42 : 142/42\n"
+ "100/0 : 200/0\n"
+ "2/12-20 : */*\n"
+ "1/22-30 : 1/*+1000\n"
+ "1/2-9,11-19,31-* : */*\n"
+ "0/*;3-41/*;42/0-41,43-*;43-99/*;100/1-*;101-*/* : *+100/*\n"
+ );
+
+ std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au.gds");
+ db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
+}
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index a60e37a89..430a31f25 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -174,7 +174,7 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
lp.datatype = 0;
}
- std::pair ll = m_layer_map.logical (lp);
+ std::pair ll = m_layer_map.logical (lp, layout);
if (ll.first) {
@@ -243,7 +243,7 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
return std::make_pair (false, 0);
}
- std::pair ll = m_layer_map.logical (name);
+ std::pair ll = m_layer_map.logical (name, layout);
if (ll.first) {
@@ -256,14 +256,14 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
} else {
- std::pair ll_raw = m_layer_map.logical (n);
+ std::pair ll_raw = m_layer_map.logical (n, layout);
int ln = -1;
if (ll_raw.first && (ln = layout.get_properties (ll_raw.second).layer) >= 0) {
m_layer_map.map (db::LayerProperties (name), layout.layers (), db::LayerProperties (ln, dt, name));
m_layer_map.prepare (layout);
- return m_layer_map.logical (name);
+ return m_layer_map.logical (name, layout);
} else if (! m_create_layers) {
diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
index d3cc00511..2d084c313 100644
--- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
+++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
@@ -554,7 +554,7 @@ OASISReader::warn (const std::string &msg)
std::pair
OASISReader::open_dl (db::Layout &layout, const LDPair &dl, bool create)
{
- std::pair ll = m_layer_map.logical (dl);
+ std::pair ll = m_layer_map.logical (dl, layout);
if (ll.first) {
return ll;
diff --git a/testdata/gds/alm_au.gds b/testdata/gds/alm_au.gds
new file mode 100644
index 000000000..513fcb589
Binary files /dev/null and b/testdata/gds/alm_au.gds differ