From 99d3610a6a2f30fd795feb3e079eeefb04ecd25a Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 28 Mar 2020 22:49:57 +0100
Subject: [PATCH] Implemented #527 (wildcard layer mapping targets)
commit d77702cd86066f3a97d740a95923fa598c2ff07b
Author: Matthias Koefferlein
Date: Sat Mar 28 21:28:39 2020 +0100
Wildcard expansion feature on layer mapping
Finished feature, added doc and test.
The solution is to use placeholder indexes for the
layer mapping which are substituted by the real
layers when they are encountered.
commit af60b5f18acfe3c5e2f1d4e6bc6ee752a246dc0d
Author: Matthias Koefferlein
Date: Sat Mar 28 19:11:32 2020 +0100
Preparations for new feature: introduce relative and wildcard target layer specs
---
src/db/db/dbLayerProperties.cc | 83 +++-
src/db/db/dbLayerProperties.h | 18 +-
src/db/db/dbNamedLayerReader.cc | 6 +-
src/db/db/dbStreamLayers.cc | 215 +++++++--
src/db/db/dbStreamLayers.h | 105 ++++-
src/db/db/gsiDeclDbLayout.cc | 14 +-
src/db/unit_tests/dbStreamLayerTests.cc | 409 ++++++++++++++++++
src/db/unit_tests/dbStreamLayers.cc | 121 ------
src/db/unit_tests/unit_tests.pro | 4 +-
src/lay/lay/doc/about/layer_mapping.xml | 80 ++++
.../streamers/dxf/db_plugin/dbDXFReader.cc | 2 +-
.../gds2/db_plugin/dbGDS2ReaderBase.cc | 2 +-
.../streamers/gds2/unit_tests/dbGDS2Reader.cc | 43 ++
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 8 +-
.../oasis/db_plugin/dbOASISReader.cc | 2 +-
testdata/gds/alm_au.gds | Bin 0 -> 6802 bytes
16 files changed, 903 insertions(+), 209 deletions(-)
create mode 100644 src/db/unit_tests/dbStreamLayerTests.cc
delete mode 100644 src/db/unit_tests/dbStreamLayers.cc
create mode 100644 testdata/gds/alm_au.gds
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 0000000000000000000000000000000000000000..513fcb58926a16f0a778eeb9c2f77f1ef9c5b1f5
GIT binary patch
literal 6802
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