mirror of https://github.com/KLayout/klayout.git
Implemented #527 (wildcard layer mapping targets)
commit d77702cd86066f3a97d740a95923fa598c2ff07b
Author: Matthias Koefferlein <matthias@koefferlein.de>
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 <matthias@koefferlein.de>
Date: Sat Mar 28 19:11:32 2020 +0100
Preparations for new feature: introduce relative and wildcard target layer specs
This commit is contained in:
parent
53f69ea90d
commit
99d3610a6a
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
|
|||
|
||||
std::pair<bool, unsigned int> 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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,13 +71,31 @@ LayerMap::LayerMap ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
std::pair<bool, unsigned int>
|
||||
LayerMap::logical (const LDPair &p) const
|
||||
{
|
||||
return logical_internal (p, false);
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
LayerMap::logical (const std::string &n) const
|
||||
{
|
||||
return logical_internal (n, false);
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
LayerMap::logical (const db::LayerProperties &p) const
|
||||
{
|
||||
return logical_internal (p, false);
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
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<bool, unsigned int>
|
||||
LayerMap::logical (const std::string &n) const
|
||||
LayerMap::logical_internal (const std::string &n, bool allow_placeholder) const
|
||||
{
|
||||
std::map<std::string, unsigned int>::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<bool, unsigned int>
|
||||
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<bool, unsigned int> m = logical (db::LDPair (p.layer, p.datatype));
|
||||
std::pair<bool, unsigned int> m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
|
||||
if (m.first) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
if (! p.name.empty ()) {
|
||||
std::pair<bool, unsigned int> m = logical (p.name);
|
||||
std::pair<bool, unsigned int> 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<unsigned int>::max () - l);
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
LayerMap::logical (const db::LayerProperties &p, db::Layout &layout) const
|
||||
{
|
||||
std::pair<bool, unsigned int> l = logical_internal (p, true);
|
||||
if (l.first && is_placeholder (l.second)) {
|
||||
return const_cast<LayerMap *> (this)->substitute_placeholder (p, l.second, layout);
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
LayerMap::logical (const db::LDPair &p, db::Layout &layout) const
|
||||
{
|
||||
std::pair<bool, unsigned int> l = logical_internal (p, true);
|
||||
if (l.first && is_placeholder (l.second)) {
|
||||
return const_cast<LayerMap *> (this)->substitute_placeholder (db::LayerProperties (p.layer, p.datatype), l.second, layout);
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int>
|
||||
LayerMap::substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout)
|
||||
{
|
||||
const db::LayerProperties &lp_ph = m_placeholders [std::numeric_limits<unsigned int>::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<ld_type>::max ()) {
|
||||
return "*";
|
||||
} else if (l2 == std::numeric_limits<ld_type>::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<unsigned int, LayerProperties>::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<unsigned int>::max ();
|
||||
|
||||
std::map<unsigned int, unsigned int> real_layers;
|
||||
std::set<unsigned int> mapped_layers;
|
||||
|
||||
|
|
@ -190,16 +257,33 @@ LayerMap::prepare (db::Layout &layout)
|
|||
|
||||
std::vector<unsigned int> old_layers = get_layers ();
|
||||
for (std::vector<unsigned int>::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 <bool, unsigned int> 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 <bool, unsigned int> 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<unsigned int, LayerProperties>::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<ld_type>::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<ld_type>::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<ld_type>::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<ld_type>::max (), dt, op2);
|
||||
}
|
||||
|
||||
if (l >= m_next_index) {
|
||||
m_next_index = l + 1;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "gsiObject.h"
|
||||
|
||||
#include <map>
|
||||
#include <limits>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -57,6 +58,58 @@ public:
|
|||
*/
|
||||
typedef int ld_type;
|
||||
|
||||
/**
|
||||
* @brief Some definitions to declare wildcard and relative datatypes or layers
|
||||
*/
|
||||
inline ld_type any_ld ()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline bool is_any_ld (ld_type ld)
|
||||
{
|
||||
return ld == -1;
|
||||
}
|
||||
|
||||
inline bool is_static_ld (ld_type ld)
|
||||
{
|
||||
return ld >= 0;
|
||||
}
|
||||
|
||||
inline ld_type relative_ld (ld_type ld)
|
||||
{
|
||||
if (ld < 0) {
|
||||
return std::numeric_limits<ld_type>::min() - ld;
|
||||
} else {
|
||||
// NOTE: this way "any_ld" is equivalent to "relative_ld(0)"
|
||||
return -ld - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline ld_type is_relative_ld (ld_type ld)
|
||||
{
|
||||
return ld < 0;
|
||||
}
|
||||
|
||||
inline ld_type ld_offset (ld_type ld)
|
||||
{
|
||||
if (ld < 0) {
|
||||
ld_type neg = ld - std::numeric_limits<ld_type>::min();
|
||||
ld_type pos = -(ld + 1);
|
||||
return neg < pos ? -neg : pos;
|
||||
} else {
|
||||
return ld;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief With a relative b, b is added to a. Otherwise b replaces a.
|
||||
*/
|
||||
inline ld_type ld_combine (ld_type a, ld_type b)
|
||||
{
|
||||
return is_relative_ld (b) ? a + ld_offset (b) : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A struct for a layer/datatype pair)
|
||||
*/
|
||||
|
|
@ -162,7 +215,28 @@ public:
|
|||
*/
|
||||
std::pair<bool, unsigned int> logical (const db::LayerProperties &p) const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Query or install a layer mapping from a name or LDPair
|
||||
*
|
||||
* @return A pair telling if the layer is mapped (first=true) and
|
||||
* the logical layer mapped (second) if this is the case.
|
||||
*
|
||||
* @param p The layer that is looked for
|
||||
*
|
||||
* This version is used for wildcard and relative mapping. In this case,
|
||||
* the logical layers are placeholder values which will be replaced by
|
||||
* true layers during this method if a new layer is requested.
|
||||
*/
|
||||
std::pair<bool, unsigned int> logical (const db::LayerProperties &p, db::Layout &layout) const;
|
||||
|
||||
/**
|
||||
* @brief Query or install a layer mapping from a LDPair
|
||||
*
|
||||
* See the version for LayerProperties about details.
|
||||
*/
|
||||
std::pair<bool, unsigned int> logical (const db::LDPair &p, db::Layout &layout) const;
|
||||
|
||||
/**
|
||||
* @brief String description for the mapping of a logical layer
|
||||
*
|
||||
* @return A string describing the mapping (an empty string if
|
||||
|
|
@ -263,12 +337,23 @@ public:
|
|||
* sequence of numbers, separated by comma values or a range
|
||||
* separated by a hyphen. Examples are: "1/2", "1-5/0", "1,2,5/0",
|
||||
* "1/5;5/6".
|
||||
*
|
||||
* layer/datatype wildcards can be specified with "*". When "*" is used
|
||||
* for the upper limit, it is equivalent to "all layer above". When used
|
||||
* alone, it is equivalent to "all layers". Examples: "1 / *", "* / 10-*".
|
||||
*
|
||||
* Named layers are specified simply by specifying the name, if
|
||||
* necessary in single or double quotes (if the name begins with a digit or
|
||||
* contains non-word characters). layer/datatype and name descriptions can
|
||||
* be mixed, i.e. "AA;1/5" (meaning: name "AA" or layer 1/datatype 5).
|
||||
*
|
||||
* A target layer can be specified with the ":<target>" notation, where
|
||||
* target is a valid string for a LayerProperties() object.
|
||||
*
|
||||
* A target can include relative layer/datatype specifications and wildcards.
|
||||
* For example, "1-10/0: *+1/0" will add 1 to the original layer number.
|
||||
* "1-10/0-50: * / *" will use the original layers.
|
||||
*
|
||||
* This method will throw a LayerSpecFormatException if
|
||||
* something is wrong with the format string
|
||||
*/
|
||||
|
|
@ -282,8 +367,10 @@ public:
|
|||
/**
|
||||
* @brief Prepares a layer mapping object for reading
|
||||
*
|
||||
* This replaces all layer indexes by ones either in the layout or it will create new layers
|
||||
* in the layout
|
||||
* This replaces all layer indexes by ones from the layout or it will create new layers
|
||||
* if required. Note that for relative and wildcard targets (except '* / *'), the layer
|
||||
* indexes will not be the true indexes but placeholders. They will be replaced later
|
||||
* when calling logical with a layout argument.
|
||||
*/
|
||||
void prepare (db::Layout &layout);
|
||||
|
||||
|
|
@ -362,10 +449,18 @@ private:
|
|||
ld_map m_ld_map;
|
||||
std::map<std::string, unsigned int> m_name_map;
|
||||
std::map<unsigned int, LayerProperties> m_target_layers;
|
||||
std::vector<LayerProperties> m_placeholders;
|
||||
unsigned int m_next_index;
|
||||
|
||||
void insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &t);
|
||||
void insert (const std::string &name, unsigned int l, const LayerProperties &t);
|
||||
void insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties *t);
|
||||
void insert (const std::string &name, unsigned int l, const LayerProperties *t);
|
||||
|
||||
std::pair<bool, unsigned int> logical_internal (const LDPair &p, bool allow_placeholder) const;
|
||||
std::pair<bool, unsigned int> logical_internal (const std::string &name, bool allow_placeholder) const;
|
||||
std::pair<bool, unsigned int> logical_internal (const db::LayerProperties &p, bool allow_placeholder) const;
|
||||
|
||||
std::pair<bool, unsigned int> substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout);
|
||||
bool is_placeholder (unsigned int l) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,11 +106,11 @@ db::LayerProperties *ctor_layer_info_name (const std::string &name)
|
|||
}
|
||||
|
||||
static
|
||||
db::LayerProperties li_from_string (const char *s)
|
||||
db::LayerProperties li_from_string (const char *s, bool as_target)
|
||||
{
|
||||
tl::Extractor ex (s);
|
||||
db::LayerProperties lp;
|
||||
lp.read (ex);
|
||||
lp.read (ex, as_target);
|
||||
return lp;
|
||||
}
|
||||
|
||||
|
|
@ -152,21 +152,27 @@ Class<db::LayerProperties> decl_LayerInfo ("db", "LayerInfo",
|
|||
"\n"
|
||||
"This method was added in version 0.18.\n"
|
||||
) +
|
||||
gsi::method ("from_string", &li_from_string, gsi::arg ("s"),
|
||||
gsi::method ("from_string", &li_from_string, gsi::arg ("s"), gsi::arg ("as_target", false),
|
||||
"@brief Create a layer info object from a string\n"
|
||||
"@param The string\n"
|
||||
"@return The LayerInfo object\n"
|
||||
"\n"
|
||||
"If 'as_target' is true, relative specifications such as '*+1' for layer or datatype are permitted.\n"
|
||||
"\n"
|
||||
"This method will take strings as produced by \\to_s and create a \\LayerInfo object from them. "
|
||||
"The format is either \"layer\", \"layer/datatype\", \"name\" or \"name (layer/datatype)\".\n"
|
||||
"\n"
|
||||
"This method was added in version 0.23.\n"
|
||||
"The 'as_target' argument has been added in version 0.26.5.\n"
|
||||
) +
|
||||
gsi::method ("to_s", &db::LayerProperties::to_string,
|
||||
gsi::method ("to_s", &db::LayerProperties::to_string, gsi::arg ("as_target", false),
|
||||
"@brief Convert the layer info object to a string\n"
|
||||
"@return The string\n"
|
||||
"\n"
|
||||
"If 'as_target' is true, wildcard and relative specifications are formatted such such.\n"
|
||||
"\n"
|
||||
"This method was added in version 0.18.\n"
|
||||
"The 'as_target' argument has been added in version 0.26.5.\n"
|
||||
) +
|
||||
gsi::method ("==", &db::LayerProperties::operator==, gsi::arg ("b"),
|
||||
"@brief Compares two layer info objects\n"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,409 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbStreamLayers.h"
|
||||
#include "dbLayout.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
db::LayerMap lm;
|
||||
|
||||
lm.map (db::LDPair (1, 5), 17);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (1, 6)).first, false);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (1, 5)).first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (1, 5)).second, (unsigned int) 17);
|
||||
|
||||
lm.map (db::LDPair (1, 0), db::LDPair (5,0), 18);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (2, 0)).first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (2, 0)).second, (unsigned int) 18);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (0, 0)).first, false);
|
||||
|
||||
EXPECT_EQ (lm.mapping_str (18), "1/0;2-5/0");
|
||||
EXPECT_EQ (lm.mapping_str (17), "1/5");
|
||||
|
||||
lm.map (db::LDPair (2, 2), 18);
|
||||
EXPECT_EQ (lm.mapping_str (18), "1/0;2/0,2;3-5/0");
|
||||
EXPECT_EQ (lm.mapping (18).to_string (), "3/0"); // any of those above!
|
||||
|
||||
lm.map (db::LDPair (2, 3), 15, db::LayerProperties (17, 18));
|
||||
EXPECT_EQ (lm.mapping_str (15), "2/3 : 17/18");
|
||||
|
||||
lm.map ("WN", 22);
|
||||
EXPECT_EQ (lm.mapping_str (22), "WN");
|
||||
EXPECT_EQ (lm.mapping (22).to_string (), "WN");
|
||||
lm.map (db::LDPair (2, 8), 22);
|
||||
EXPECT_EQ (lm.mapping (22).to_string (), "WN (2/8)");
|
||||
|
||||
lm.map ("AA", 14, db::LayerProperties ("GC"));
|
||||
EXPECT_EQ (lm.mapping_str (14), "AA : GC");
|
||||
EXPECT_EQ (lm.mapping (14).to_string (), "GC");
|
||||
lm.map (db::LDPair (7, 8), 14);
|
||||
EXPECT_EQ (lm.mapping (14).to_string (), "GC (7/8)");
|
||||
|
||||
lm.map_expr ("XP;10/7-8 : XN", 13);
|
||||
EXPECT_EQ (lm.mapping_str (13), "10/7-8;XP : XN");
|
||||
EXPECT_EQ (lm.logical ("XP").second, (unsigned int) 13);
|
||||
EXPECT_EQ (lm.logical ("XP").first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 6)).first, false);
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 7)).first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 7)).second, (unsigned int) 13);
|
||||
|
||||
EXPECT_EQ (lm.mapping (13).to_string (), "XN (10/7)");
|
||||
|
||||
lm.clear ();
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 7)).first, false);
|
||||
lm.map_expr ("'XP';10/7-8 : XN", 13);
|
||||
EXPECT_EQ (lm.mapping_str (13), "10/7-8;XP : XN");
|
||||
}
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
db::LayerMap lm;
|
||||
|
||||
lm.map (db::LDPair (1, 5), 17);
|
||||
lm.map (db::LDPair (1, 0), db::LDPair (5,0), 18);
|
||||
lm.map (db::LDPair (2, 2), 18);
|
||||
lm.map (db::LDPair (2, 3), 15, db::LayerProperties (17, 18));
|
||||
lm.map ("WN", 22);
|
||||
lm.map ("AA", 14, db::LayerProperties ("GC"));
|
||||
lm.map_expr ("XP;10/7-8 : XN", 13);
|
||||
|
||||
EXPECT_EQ (lm.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
EXPECT_EQ (lm.to_string_file_format (), "10/7-8;XP : XN\nAA : GC\n2/3 : 17/18\n1/5\n1/0;2/0,2;3-5/0\nWN\n");
|
||||
|
||||
db::LayerMap lm2;
|
||||
db::LayerMap lm2read;
|
||||
lm2 = db::LayerMap::from_string_file_format (lm2.to_string_file_format ());
|
||||
EXPECT_EQ (lm2.to_string (), "layer_map()");
|
||||
tl::Extractor (lm2.to_string ()).read (lm2read);
|
||||
EXPECT_EQ (lm2read.to_string (), "layer_map()");
|
||||
lm2 = db::LayerMap::from_string_file_format (lm.to_string_file_format ());
|
||||
EXPECT_EQ (lm2.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
tl::Extractor (lm2.to_string ()).read (lm2read);
|
||||
EXPECT_EQ (lm2read.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
|
||||
std::string ff =
|
||||
"\n"
|
||||
"\t // a comment\n"
|
||||
"10/7-8;XP:XN \t # another comment\n"
|
||||
"\n"
|
||||
" AA\t: GC\n"
|
||||
" 2/3 : 17/18\n"
|
||||
" 1 / 5 \n"
|
||||
"\t\t1/0;2/0,2;3-5/0\n"
|
||||
"# commented out: 1/0;2/0,2;3-5/0\n"
|
||||
"WN";
|
||||
|
||||
lm2 = db::LayerMap::from_string_file_format (ff);
|
||||
EXPECT_EQ (lm2.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
{
|
||||
EXPECT_EQ (db::is_relative_ld (1), false);
|
||||
EXPECT_EQ (db::is_relative_ld (0), false);
|
||||
EXPECT_EQ (db::is_static_ld (0), true);
|
||||
EXPECT_EQ (db::is_relative_ld (db::relative_ld (0)), true);
|
||||
EXPECT_EQ (db::is_relative_ld (db::any_ld ()), true);
|
||||
EXPECT_EQ (db::is_relative_ld (db::relative_ld (1)), true);
|
||||
EXPECT_EQ (db::is_relative_ld (db::relative_ld (-1)), true);
|
||||
EXPECT_EQ (db::is_static_ld (db::relative_ld (-1)), false);
|
||||
EXPECT_EQ (db::is_any_ld (db::any_ld ()), true);
|
||||
EXPECT_EQ (db::is_any_ld (1), false);
|
||||
EXPECT_EQ (db::is_any_ld (db::relative_ld (-1)), false);
|
||||
EXPECT_EQ (db::ld_offset (db::relative_ld (-1)), -1);
|
||||
EXPECT_EQ (db::ld_offset (db::relative_ld (-100)), -100);
|
||||
EXPECT_EQ (db::ld_offset (db::relative_ld (0)), 0);
|
||||
EXPECT_EQ (db::ld_offset (db::relative_ld (1)), 1);
|
||||
EXPECT_EQ (db::ld_offset (db::relative_ld (100)), 100);
|
||||
EXPECT_EQ (db::ld_offset (100), 100);
|
||||
EXPECT_EQ (db::ld_combine (1, db::relative_ld (100)), 101);
|
||||
EXPECT_EQ (db::ld_combine (1, 100), 100);
|
||||
EXPECT_EQ (db::ld_combine (100, db::relative_ld (-1)), 99);
|
||||
}
|
||||
|
||||
TEST(4)
|
||||
{
|
||||
db::LayerMap lm;
|
||||
|
||||
unsigned int n = 0;
|
||||
|
||||
// named, no catch-all
|
||||
lm.map (db::LayerProperties ("NAME"), n++);
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('NAME')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// single layer
|
||||
lm.map (db::LayerProperties (1, 2), n++);
|
||||
// single layer, wildcard target
|
||||
lm.map (db::LayerProperties (1, 3), n++, db::LayerProperties (db::any_ld (), db::any_ld ()));
|
||||
lm.map (db::LayerProperties (1, 4), n++, db::LayerProperties (2, db::any_ld ()));
|
||||
lm.map (db::LayerProperties (1, 5), n++, db::LayerProperties (db::any_ld (), 15));
|
||||
// single layer, relative target
|
||||
lm.map (db::LayerProperties (1, 6), n++, db::LayerProperties (db::any_ld (), db::relative_ld (3)));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('1/2';'1/3 : */*';'1/4 : 2/*';'1/5 : */15';'1/6 : */*+3')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// datatype catch-all
|
||||
lm.map (db::LayerProperties (1, db::any_ld ()), n++);
|
||||
// datatype catch-all, fixed targets
|
||||
lm.map (db::LayerProperties (2, db::any_ld ()), n++, db::LayerProperties (12, 2));
|
||||
// datatype catch-all, wildcard targets
|
||||
lm.map (db::LayerProperties (3, db::any_ld ()), n++, db::LayerProperties (db::any_ld (), 2));
|
||||
lm.map (db::LayerProperties (4, db::any_ld ()), n++, db::LayerProperties (db::any_ld (), db::any_ld ()));
|
||||
// datatype catch-all, relative targets
|
||||
lm.map (db::LayerProperties (5, db::any_ld ()), n++, db::LayerProperties (15, db::relative_ld (0)));
|
||||
lm.map (db::LayerProperties (6, db::any_ld ()), n++, db::LayerProperties (16, db::relative_ld (-1)));
|
||||
lm.map (db::LayerProperties (7, db::any_ld ()), n++, db::LayerProperties (17, db::relative_ld (1)));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('1/*';'2/* : 12/2';'3/* : */2';'4/* : */*';'5/* : 15/*';'6/* : 16/*-1';'7/* : 17/*+1')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// layer catch-all
|
||||
lm.map (db::LayerProperties (db::any_ld (), 1), n++);
|
||||
// layer catch-all, fixed targets
|
||||
lm.map (db::LayerProperties (db::any_ld (), 2), n++, db::LayerProperties (1, 12));
|
||||
// layer catch-all, wildcard targets
|
||||
lm.map (db::LayerProperties (db::any_ld (), 3), n++, db::LayerProperties (db::any_ld (), 2));
|
||||
lm.map (db::LayerProperties (db::any_ld (), 4), n++, db::LayerProperties (db::any_ld (), db::any_ld ()));
|
||||
// layer catch-all, relative targets
|
||||
lm.map (db::LayerProperties (db::any_ld (), 5), n++, db::LayerProperties (2, db::relative_ld (0)));
|
||||
lm.map (db::LayerProperties (db::any_ld (), 6), n++, db::LayerProperties (2, db::relative_ld (-1)));
|
||||
lm.map (db::LayerProperties (db::any_ld (), 7), n++, db::LayerProperties (2, db::relative_ld (1)));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/1';'*/2 : 1/12';'*/3 : */2';'*/4 : */*';'*/5 : 2/*';'*/6 : 2/*-1';'*/7 : 2/*+1')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// layer and datatype catch-all
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++);
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/*')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// layer and datatype catch-all, fixed targets
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++, db::LayerProperties (1, 2));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/* : 1/2')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// layer and datatype catch-all, wildcard targets
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++, db::LayerProperties (db::any_ld (), 2));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/* : */2')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++, db::LayerProperties (db::any_ld (), db::any_ld ()));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/* : */*')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
// layer and datatype catch-all, relative targets
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++, db::LayerProperties (2, db::relative_ld (0)));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/* : 2/*')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++, db::LayerProperties (2, db::relative_ld (-1)));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/* : 2/*-1')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
lm.clear ();
|
||||
n = 0;
|
||||
|
||||
lm.map (db::LayerProperties (db::any_ld (), db::any_ld ()), n++, db::LayerProperties (2, db::relative_ld (1)));
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/* : 2/*+1')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
}
|
||||
|
||||
TEST(5)
|
||||
{
|
||||
db::LayerMap lm;
|
||||
|
||||
unsigned int n = 0;
|
||||
|
||||
// refinement
|
||||
// all
|
||||
lm.map_expr ("*/*", n++);
|
||||
// some
|
||||
lm.map_expr ("*/1-10", n++);
|
||||
// others
|
||||
lm.map_expr ("*/5,15", n++);
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('*/0,11-14,16-*';'*/1-4,6-10';'*/5,15')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
|
||||
// orthogonal layer refinement
|
||||
lm.map_expr ("17/*", n++);
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('0-16/0,11-14,16-*;18-*/0,11-14,16-*';'0-16/1-4,6-10;18-*/1-4,6-10';'0-16/5,15;18-*/5,15';'17/*')"
|
||||
);
|
||||
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
|
||||
}
|
||||
|
||||
static std::string layers_to_string (const db::Layout &ly)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
for (unsigned int i = 0; i < ly.layers (); ++i) {
|
||||
if (ly.is_valid_layer (i)) {
|
||||
if (! s.empty ()) {
|
||||
s += ",";
|
||||
}
|
||||
s += ly.get_properties (i).to_string ();
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
TEST(6)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::LayerMap lm;
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "");
|
||||
|
||||
unsigned int n = 0;
|
||||
lm.map_expr ("1/0", n++);
|
||||
lm.map_expr ("2/* : */*", n++);
|
||||
lm.map_expr ("3/10-*", n++); // all layers are mapped to 3/10
|
||||
|
||||
lm.prepare (ly);
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "1/0,3/10");
|
||||
|
||||
std::pair<bool, unsigned int> p;
|
||||
p = lm.logical (db::LayerProperties (1, 0));
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 0);
|
||||
|
||||
p = lm.logical (db::LayerProperties (2, 0));
|
||||
EXPECT_EQ (p.first, false);
|
||||
|
||||
p = lm.logical (db::LayerProperties (3, 0));
|
||||
EXPECT_EQ (p.first, false);
|
||||
|
||||
p = lm.logical (db::LayerProperties (3, 10));
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 1);
|
||||
|
||||
p = lm.logical (db::LayerProperties (3, 99));
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 1);
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "1/0,3/10");
|
||||
|
||||
// this will create layer 2/0 in the layout
|
||||
p = lm.logical (db::LayerProperties (2, 0), ly);
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 2);
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0");
|
||||
|
||||
p = lm.logical (db::LayerProperties (2, 0));
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 2);
|
||||
|
||||
p = lm.logical (db::LayerProperties (2, 0), ly);
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 2);
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0");
|
||||
|
||||
// this will create layer 2/0 in the layout
|
||||
p = lm.logical (db::LayerProperties (2, 42), ly);
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 3);
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0,2/42");
|
||||
|
||||
p = lm.logical (db::LayerProperties (2, 42));
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 3);
|
||||
|
||||
p = lm.logical (db::LayerProperties (2, 42), ly);
|
||||
EXPECT_EQ (p.first, true);
|
||||
EXPECT_EQ (p.second, (unsigned int) 3);
|
||||
|
||||
EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0,2/42");
|
||||
|
||||
EXPECT_EQ (lm.to_string (),
|
||||
"layer_map('1/0';'3/10-*';'2/0';'2/42';'2/1-41,43-* : */*')"
|
||||
);
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "dbStreamLayers.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
db::LayerMap lm;
|
||||
|
||||
lm.map (db::LDPair (1, 5), 17);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (1, 6)).first, false);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (1, 5)).first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (1, 5)).second, (unsigned int) 17);
|
||||
|
||||
lm.map (db::LDPair (1, 0), db::LDPair (5,0), 18);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (2, 0)).first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (2, 0)).second, (unsigned int) 18);
|
||||
EXPECT_EQ (lm.logical (db::LDPair (0, 0)).first, false);
|
||||
|
||||
EXPECT_EQ (lm.mapping_str (18), "1/0;2-5/0");
|
||||
EXPECT_EQ (lm.mapping_str (17), "1/5");
|
||||
|
||||
lm.map (db::LDPair (2, 2), 18);
|
||||
EXPECT_EQ (lm.mapping_str (18), "1/0;2/0,2;3-5/0");
|
||||
EXPECT_EQ (lm.mapping (18).to_string (), "3/0"); // any of those above!
|
||||
|
||||
lm.map (db::LDPair (2, 3), 15, db::LayerProperties (17, 18));
|
||||
EXPECT_EQ (lm.mapping_str (15), "2/3 : 17/18");
|
||||
|
||||
lm.map ("WN", 22);
|
||||
EXPECT_EQ (lm.mapping_str (22), "WN");
|
||||
EXPECT_EQ (lm.mapping (22).to_string (), "WN");
|
||||
lm.map (db::LDPair (2, 8), 22);
|
||||
EXPECT_EQ (lm.mapping (22).to_string (), "WN (2/8)");
|
||||
|
||||
lm.map ("AA", 14, db::LayerProperties ("GC"));
|
||||
EXPECT_EQ (lm.mapping_str (14), "AA : GC");
|
||||
EXPECT_EQ (lm.mapping (14).to_string (), "GC");
|
||||
lm.map (db::LDPair (7, 8), 14);
|
||||
EXPECT_EQ (lm.mapping (14).to_string (), "GC (7/8)");
|
||||
|
||||
lm.map_expr ("XP;10/7-8 : XN", 13);
|
||||
EXPECT_EQ (lm.mapping_str (13), "10/7-8;XP : XN");
|
||||
EXPECT_EQ (lm.logical ("XP").second, (unsigned int) 13);
|
||||
EXPECT_EQ (lm.logical ("XP").first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 6)).first, false);
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 7)).first, true);
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 7)).second, (unsigned int) 13);
|
||||
|
||||
EXPECT_EQ (lm.mapping (13).to_string (), "XN (10/7)");
|
||||
|
||||
lm.clear ();
|
||||
EXPECT_EQ (lm.logical (db::LDPair(10, 7)).first, false);
|
||||
lm.map_expr ("'XP';10/7-8 : XN", 13);
|
||||
EXPECT_EQ (lm.mapping_str (13), "10/7-8;XP : XN");
|
||||
}
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
db::LayerMap lm;
|
||||
|
||||
lm.map (db::LDPair (1, 5), 17);
|
||||
lm.map (db::LDPair (1, 0), db::LDPair (5,0), 18);
|
||||
lm.map (db::LDPair (2, 2), 18);
|
||||
lm.map (db::LDPair (2, 3), 15, db::LayerProperties (17, 18));
|
||||
lm.map ("WN", 22);
|
||||
lm.map ("AA", 14, db::LayerProperties ("GC"));
|
||||
lm.map_expr ("XP;10/7-8 : XN", 13);
|
||||
|
||||
EXPECT_EQ (lm.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
EXPECT_EQ (lm.to_string_file_format (), "10/7-8;XP : XN\nAA : GC\n2/3 : 17/18\n1/5\n1/0;2/0,2;3-5/0\nWN\n");
|
||||
|
||||
db::LayerMap lm2;
|
||||
db::LayerMap lm2read;
|
||||
lm2 = db::LayerMap::from_string_file_format (lm2.to_string_file_format ());
|
||||
EXPECT_EQ (lm2.to_string (), "layer_map()");
|
||||
tl::Extractor (lm2.to_string ()).read (lm2read);
|
||||
EXPECT_EQ (lm2read.to_string (), "layer_map()");
|
||||
lm2 = db::LayerMap::from_string_file_format (lm.to_string_file_format ());
|
||||
EXPECT_EQ (lm2.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
tl::Extractor (lm2.to_string ()).read (lm2read);
|
||||
EXPECT_EQ (lm2read.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
|
||||
std::string ff =
|
||||
"\n"
|
||||
"\t // a comment\n"
|
||||
"10/7-8;XP:XN \t # another comment\n"
|
||||
"\n"
|
||||
" AA\t: GC\n"
|
||||
" 2/3 : 17/18\n"
|
||||
" 1 / 5 \n"
|
||||
"\t\t1/0;2/0,2;3-5/0\n"
|
||||
"# commented out: 1/0;2/0,2;3-5/0\n"
|
||||
"WN";
|
||||
|
||||
lm2 = db::LayerMap::from_string_file_format (ff);
|
||||
EXPECT_EQ (lm2.to_string (), "layer_map('10/7-8;XP : XN';'AA : GC';'2/3 : 17/18';'1/5';'1/0;2/0,2;3-5/0';'WN')");
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,6 @@ SOURCES = \
|
|||
dbShape.cc \
|
||||
dbShapeRepository.cc \
|
||||
dbShapes.cc \
|
||||
dbStreamLayers.cc \
|
||||
dbText.cc \
|
||||
dbTilingProcessor.cc \
|
||||
dbTrans.cc \
|
||||
|
|
@ -73,7 +72,8 @@ SOURCES = \
|
|||
dbLayoutVsSchematicTests.cc \
|
||||
dbLayoutQueryTests.cc \
|
||||
dbPolygonToolsTests.cc \
|
||||
dbTechnologyTests.cc
|
||||
dbTechnologyTests.cc \
|
||||
dbStreamLayerTests.cc
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||
|
|
|
|||
|
|
@ -93,5 +93,85 @@
|
|||
are empty lines. Comments can be inserted using the "#" character in front of the comment.
|
||||
</p>
|
||||
|
||||
<h2>Wildcards</h2>
|
||||
|
||||
<p>
|
||||
Source layers can be specified using wildcards. A wildcard is a "*" character
|
||||
matching "any layer".
|
||||
Examples for such expressions are:
|
||||
</p>
|
||||
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr>
|
||||
<td><b>10-*/0</b></td>
|
||||
<td>Matching layer 10 and above, datatype 0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>*/10</b></td>
|
||||
<td>Matching datatype 10 of every layer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>0-5,10-*/*</b></td>
|
||||
<td>Matching layer 0 to 5 (inclusive) and above 10, all datatypes.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h2>Wildcard expansion and relative layer mapping</h2>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr>
|
||||
<td><b>10-*/0 : */10</b></td>
|
||||
<td>Maintain layers for layer 10 and above and map datatype to 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>10-*/0 : */*</b></td>
|
||||
<td>Select layers 10 and above, datatype 0 and maintain these as individual layers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>1/* : 2/*</b></td>
|
||||
<td>Map layer number 1 to 2, maintain all datatypes</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
|
||||
<table border="0" cellspacing="2" cellpadding="0">
|
||||
<tr>
|
||||
<td><b>10-20/*: *+1000/*</b></td>
|
||||
<td>Selects all layers between 10 and 20, all datatypes. These layers will be
|
||||
read into the original layers plus 1000 for the layer number.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>10/10-*: */*-10</b></td>
|
||||
<td>Selects layer 10, datatypes 10 plus. The resulting datatypes will be 10 less starting from 0.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</doc>
|
||||
|
||||
|
|
|
|||
|
|
@ -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<bool, unsigned int> ll = layer_map ().logical (zero_layer_name);
|
||||
std::pair<bool, unsigned int> ll = layer_map ().logical (zero_layer_name, layout);
|
||||
if (ll.first) {
|
||||
|
||||
// create the layer if it is not part of the layout yet.
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ GDS2ReaderBase::finish_element (db::PropertiesRepository &rep)
|
|||
std::pair <bool, unsigned int>
|
||||
GDS2ReaderBase::open_dl (db::Layout &layout, const LDPair &dl, bool create)
|
||||
{
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (dl);
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (dl, layout);
|
||||
if (ll.first) {
|
||||
|
||||
return ll;
|
||||
|
|
|
|||
|
|
@ -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<db::CommonReaderOptions> ().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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
|
|||
lp.datatype = 0;
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (lp);
|
||||
std::pair<bool, unsigned int> 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<bool, unsigned int> ll = m_layer_map.logical (name);
|
||||
std::pair<bool, unsigned int> 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<bool, unsigned int> ll_raw = m_layer_map.logical (n);
|
||||
std::pair<bool, unsigned int> 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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -554,7 +554,7 @@ OASISReader::warn (const std::string &msg)
|
|||
std::pair <bool, unsigned int>
|
||||
OASISReader::open_dl (db::Layout &layout, const LDPair &dl, bool create)
|
||||
{
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (dl);
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (dl, layout);
|
||||
if (ll.first) {
|
||||
|
||||
return ll;
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue