From 2300c391ae6da1272b544daa8e16b9953a51e9ae Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 21 Nov 2020 00:38:25 +0100
Subject: [PATCH 01/29] Better alignment DEF layer map reader with
specification (still some options are ignore).
---
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 197 ++++++++++++------
.../lefdef/db_plugin/dbLEFDEFImporter.h | 1 +
2 files changed, 131 insertions(+), 67 deletions(-)
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index c4628b38c..647dd099a 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -813,6 +813,26 @@ LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpos
m_layer_map.map (lp, layer);
}
+static bool try_read_layers (tl::Extractor &ex, std::vector &layers)
+{
+ int l = 0;
+ if (! ex.try_read (l)) {
+ return false;
+ }
+ layers.push_back (l);
+
+ if (ex.test (",")) {
+ do {
+ if (! ex.try_read (l)) {
+ return false;
+ }
+ layers.push_back (l);
+ } while (ex.test (","));
+ }
+
+ return true;
+}
+
void
LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
{
@@ -832,6 +852,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
purpose_translation ["NET"] = Routing;
purpose_translation ["VIA"] = ViaGeometry;
purpose_translation ["BLOCKAGE"] = Blockage;
+ purpose_translation ["ALL"] = All;
std::map purpose_translation_rev;
for (std::map::const_iterator i = purpose_translation.begin (); i != purpose_translation.end (); ++i) {
@@ -853,112 +874,154 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
std::string w1, w2;
int layer = 0, datatype = 0;
+ std::vector layers;
size_t max_purpose_str = 10;
- if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) {
+ if (! ex.try_read_word (w1) || ! ex.try_read_word (w2, "._$,/:") || ! try_read_layers (ex, layers) || ! ex.try_read (datatype)) {
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d not understood - skipped")), path, ts.line_number ());
+ continue;
+ }
- if (w1 == "DIEAREA") {
+ if (layers.size () > 1) {
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: mapping to multiple layers not supported currently - first one taken")), path, ts.line_number ());
+ }
+ layer = layers.front ();
- layer_map [std::make_pair (std::string (), std::make_pair (Outline, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "OUTLINE");
+ if (w1 == "DIEAREA") {
- } else if (w1 == "REGIONS") {
+ layer_map [std::make_pair (std::string (), std::make_pair (Outline, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "OUTLINE");
- layer_map [std::make_pair (std::string (), std::make_pair (Regions, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "REGIONS");
+ } else if (w1 == "REGIONS") {
- } else if (w1 == "BLOCKAGE") {
+ layer_map [std::make_pair (std::string (), std::make_pair (Regions, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "REGIONS");
- layer_map [std::make_pair (std::string (), std::make_pair (PlacementBlockage, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "PLACEMENT_BLK");
+ } else if (w1 == "BLOCKAGE") {
- } else if (w1 == "NAME") {
+ layer_map [std::make_pair (std::string (), std::make_pair (PlacementBlockage, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "PLACEMENT_BLK");
- // converts a line like
- // "NAME M1/PINS,M2/PINS ..."
- // into a canonical name mapping like
- // "(M1/LABELS): M1.LABEL"
- // "(M2/LABELS): M2.LABEL"
+ } else if (w1 == "NAME") {
- std::vector layers;
- std::vector purposes = tl::split (w2, ",");
- for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
+ // converts a line like
+ // "NAME M1/PINS,M2/PINS ..."
+ // into a canonical name mapping like
+ // "(M1/LABELS): M1.LABEL"
+ // "(M2/LABELS): M2.LABEL"
+
+ std::vector layers;
+ std::vector purposes = tl::split (w2, ",");
+ for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
+ if (*p == "DIEAREA" || *p == "ALL" || *p == "COMP") {
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NAME record ignored for entity: %s")), path, ts.line_number (), *p);
+ } else {
layers.push_back (tl::split (*p, "/").front ());
}
+ }
- std::string final_name = tl::join (layers, "/") + ".LABEL";
- for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
- layer_map [std::make_pair (*l, std::make_pair (Label, (unsigned int) 0))] = db::LayerProperties (layer, datatype, final_name);
- }
+ std::string final_name = tl::join (layers, "/") + ".LABEL";
+ for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
+ layer_map [std::make_pair (*l, std::make_pair (Label, (unsigned int) 0))] = db::LayerProperties (layer, datatype, final_name);
+ }
- } else if (w1 == "COMP") {
+ } else if (w1 == "COMP") {
- // ignore "COMP (ALL) ..."
+ // ignore "COMP (ALL) ..."
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: COMP entry ignored")), path, ts.line_number ());
- } else {
+ } else {
- // converts a line like
- // "M1 SPNET,NET,PINS,LEFPINS ..."
- // into a canonical name mapping like
- // "(M1,NET): M1.NET/PINS"
- // "(M1,PINS): M1.NET/PINS"
- // (separating, translating and recombing the purposes)
+ // converts a line like
+ // "M1 SPNET,NET,PINS,LEFPINS ..."
+ // into a canonical name mapping like
+ // "(M1,NET): M1.NET/PINS"
+ // "(M1,PINS): M1.NET/PINS"
+ // (separating, translating and recombing the purposes)
- std::set > translated_purposes;
+ std::set > translated_purposes;
- std::vector purposes = tl::split (w2, ",");
- std::reverse (purposes.begin (), purposes.end ());
+ std::vector purposes = tl::split (w2, ",");
+ std::reverse (purposes.begin (), purposes.end ());
- unsigned int mask = 0;
+ unsigned int mask = 0;
- for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
+ for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
- std::string p_uc = tl::to_upper_case (*p);
- tl::Extractor ex (p_uc.c_str ());
+ std::string p_uc = tl::to_upper_case (*p);
+ tl::Extractor ex (p_uc.c_str ());
- std::string ps;
- ex.read_word_or_quoted (ps);
+ std::string ps;
+ ex.read_word_or_quoted (ps);
- if (ex.test (":")) {
+ std::map::const_iterator i = purpose_translation.find (ps);
+ if (i != purpose_translation.end ()) {
+
+ if (i->second == All) {
+ for (std::map::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
+ if (p->second != All) {
+ translated_purposes.insert (std::make_pair (p->second, mask));
+ }
+ }
+ } else {
+ translated_purposes.insert (std::make_pair (i->second, mask));
+ }
+
+ if (i->second == Routing) {
+
+ if (ex.test (":VOLTAGE:")) {
+ double f = 0.0;
+ ex.read (f);
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NET voltage constraint ignored for layer %s")), path, ts.line_number (), w1);
+ }
+
+ } else if (i->second == ViaGeometry) {
+
+ if (ex.test (":SIZE:")) {
+ std::string sz;
+ ex.read_word (sz);
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: VIA size constraint ignored for layer %s")), path, ts.line_number (), w1);
+ }
+
+ }
+
+ if (ex.test (":MASK:")) {
if (ex.test ("MASK") && ex.test (":")) {
ex.read (mask);
}
}
- std::map::const_iterator i = purpose_translation.find (ps);
- if (i != purpose_translation.end ()) {
- translated_purposes.insert (std::make_pair (i->second, mask));
- }
-
+ } else {
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: purpose %s ignored for layer %s")), path, ts.line_number (), ps, w1);
}
- // create a visual description string for the combined purposes
- std::string purpose_str;
+ }
- for (std::set >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
+ // create a visual description string for the combined purposes
+ std::string purpose_str;
- if (p != translated_purposes.begin ()) {
- purpose_str += "/";
- }
-
- std::string ps = purpose_translation_rev [p->first];
- if (p->second > 0) {
- ps += ":";
- ps += tl::to_string (p->second);
- }
-
- if ((purpose_str + ps).size () > max_purpose_str) {
- purpose_str += "...";
- break;
- } else {
- purpose_str += ps;
- }
+ for (std::set >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
+ if (p != translated_purposes.begin ()) {
+ purpose_str += "/";
}
- std::string final_name = w1 + "." + purpose_str;
-
- for (std::set >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
- layer_map [std::make_pair (w1, *p)] = db::LayerProperties (layer, datatype, final_name);
+ std::string ps = purpose_translation_rev [p->first];
+ if (p->second > 0) {
+ ps += ":";
+ ps += tl::to_string (p->second);
}
+ if ((purpose_str + ps).size () > max_purpose_str) {
+ purpose_str += "...";
+ break;
+ } else {
+ purpose_str += ps;
+ }
+
+ }
+
+ std::string final_name = w1 + "." + purpose_str;
+
+ for (std::set >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
+ layer_map [std::make_pair (w1, *p)] = db::LayerProperties (layer, datatype, final_name);
}
}
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
index f29326547..ec1da4076 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
@@ -884,6 +884,7 @@ enum LayerPurpose
Blockage, // from DEF only
PlacementBlockage, // from DEF only
Regions, // from DEF only
+ All // from DEF only
};
/**
From 6eac98907f9152eeac488a1340b56ea53a3f6351 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 21 Nov 2020 01:00:28 +0100
Subject: [PATCH 02/29] WIP: bugfix.
---
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 32 +++++++++++--------
.../lefdef/unit_tests/dbLEFDEFImportTests.cc | 12 +++++++
2 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index 647dd099a..e0f573282 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -954,16 +954,6 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
std::map::const_iterator i = purpose_translation.find (ps);
if (i != purpose_translation.end ()) {
- if (i->second == All) {
- for (std::map::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
- if (p->second != All) {
- translated_purposes.insert (std::make_pair (p->second, mask));
- }
- }
- } else {
- translated_purposes.insert (std::make_pair (i->second, mask));
- }
-
if (i->second == Routing) {
if (ex.test (":VOLTAGE:")) {
@@ -982,14 +972,28 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
}
- if (ex.test (":MASK:")) {
- if (ex.test ("MASK") && ex.test (":")) {
- ex.read (mask);
+ }
+
+ if (ex.test (":MASK:")) {
+ ex.read (mask);
+ }
+
+ if (i == purpose_translation.end ()) {
+
+ tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: purpose %s ignored for layer %s")), path, ts.line_number (), ps, w1);
+
+ } else if (i->second == All) {
+
+ for (std::map::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
+ if (p->second != All) {
+ translated_purposes.insert (std::make_pair (p->second, mask));
}
}
} else {
- tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: purpose %s ignored for layer %s")), path, ts.line_number (), ps, w1);
+
+ translated_purposes.insert (std::make_pair (i->second, mask));
+
}
}
diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
index 93921cac8..72332bedf 100644
--- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
+++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
@@ -549,6 +549,18 @@ TEST(115_componentmaskshift)
run_test (_this, "masks-2", "lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", options, false);
}
+TEST(116_name_to_ld_target_mapping)
+{
+ db::LEFDEFReaderOptions options = default_options ();
+ db::LayerMap lm = db::LayerMap::from_string_file_format ("metal1: 1\nvia1: 2\nmetal2: 3\nOUTLINE: 42/17");
+ options.set_layer_map (lm);
+
+ db::LayerMap lm_read = run_test (_this, "via_properties", "lef:in.lef+def:in.def", "au.oas.gz", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTLINE (4/0)';'metal1.VIA : metal1 (1/0)';'metal2.VIA : metal2 (3/0)';'via1.VIA : via1 (2/0)')"
+ )
+}
+
TEST(200_lefdef_plugin)
{
db::Layout ly;
From b0f25dd61e0bd2a5ad92755d67f8cb40626e3a6c Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 21 Nov 2020 20:39:31 +0100
Subject: [PATCH 03/29] Fixed DEF layer mapping for compatibility with 0.26
Problem was: general layers (e.g. OUTLINE) were not routed through
the layer map.
---
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 170 +++++++++++++-----
.../lefdef/unit_tests/dbLEFDEFImportTests.cc | 162 +++++++++++++++--
2 files changed, 277 insertions(+), 55 deletions(-)
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index e0f573282..4cc77b69d 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -1060,14 +1060,85 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
}
}
+static std::string purpose_to_name (LayerPurpose purpose)
+{
+ switch (purpose) {
+ case Outline:
+ return "OUTLINE";
+ case Regions:
+ return "REGION";
+ case PlacementBlockage:
+ return "BLOCKAGE";
+ case Routing:
+ return "NET";
+ case SpecialRouting:
+ return "SPNET";
+ case ViaGeometry:
+ return "VIA";
+ case Label:
+ return "LABEL";
+ case Pins:
+ return "PIN";
+ case LEFPins:
+ return "LEFPIN";
+ case Obstructions:
+ return "LEFOBS";
+ case Blockage:
+ return "BLK";
+ case All:
+ return "ALL";
+ }
+
+ return std::string ();
+}
+
+/**
+ * @brief Implements implicit layer mapping
+ *
+ * This is how Implicit layer mapping works:
+ *
+ * 1. For named layers (e.g. routing, pin, etc.
+ *
+ * A decorated name is formed from the basic name and the purpose string (e.g. "M1" -> "M1.PIN").
+ * With the example of "M1" and purpose Pin (decorated name "M1.PIN") and with a tech component datatype specification
+ * of "5" for "Pin", the layer map entries have the following effect:
+ *
+ * Layer map Result
+ *
+ * (nothing) M1.PIN (default/5) (only if "create_all_layers" is ON, "default" is a default number assigned by the reader)
+ * M1.PIN : 1/0 M1.PIN (1/0)
+ * M1.PIN : 1/17 M1.PIN (1/17)
+ * M1 : 1/0 M1.PIN (1/5)
+ * M1 : 1/2 M1.PIN (1/7) (datatypes will add)
+ * M1 M1.PIN (default/5)
+ * M1 : METAL1 METAL1.PIN (default/5) (name is taken from layer map and decorated)
+ * M1 : METAL1 (1/2) METAL1.PIN (1/7)
+ * M1.PIN : METAL1_PIN METAL1_PIN (default/5) (specific name is used without decoration)
+ * M1.PIN : METAL1_PIN (1/17) METAL1_PIN (1/17) (full and specific mapping)
+ *
+ * 2. For general layers (e.g. outline)
+ *
+ * By default, the name, layer and datatype are taken from the tech component's specification. The specification may
+ * lack the layer and datatype and even the name. If the name is missing, it is generated from the purpose.
+ *
+ * Here are some examples for the mapping of "OUTLINE":
+ *
+ * Tech component Layer map Result
+ *
+ * (nothing) (nothing) OUTLINE (only if "create_all_layers" is ON)
+ * OUTL (nothing) OUTL (default/0) ("default" is a default number assigned by the reader)
+ * OUTL (4/17) (nothing) OUTL (4/17)
+ * OUTL OUTL : 5/1 OUTL (5/1)
+ * OUTL (4/17) OUTL : 4/11 OUTL 4/11
+ * OUTL (4/17) 4/17 : 4/11 OUTL 4/11
+ * 4/17 4/17 : 4/11 OUTLINE 4/11
+ */
+
std::pair
LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n, LayerPurpose purpose, unsigned int mask)
{
if (n.empty ()) {
- // NOTE: the canonical name is independent from the tech component's settings
- // as is "(name)". It's used for implementing the automatic map file import
- // feature.
std::string ld;
bool produce = false;
@@ -1095,6 +1166,42 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
lp.datatype = 0;
}
+ // if no name is given, derive one from the purpose
+ if (lp.name.empty ()) {
+ lp.name = purpose_to_name (purpose);
+ }
+
+ if (lp.layer < 0) {
+ std::map::const_iterator ldef = m_default_number.find (lp.name);
+ if (ldef != m_default_number.end ()) {
+ lp.layer = ldef->second;
+ lp.datatype = 0;
+ }
+ }
+
+ // employ the layer map to find the target layer
+ std::pair ll = m_layer_map.logical (lp, layout);
+
+ if (ll.first) {
+
+ // If the layer map provides a target, use that one for the layer
+ const db::LayerProperties *lpp = m_layer_map.target (ll.second);
+ if (lpp) {
+ if (! lpp->name.empty ()) {
+ lp.name = lpp->name;
+ }
+ if (lpp->datatype >= 0) {
+ lp.datatype = lpp->datatype;
+ }
+ if (lpp->layer >= 0) {
+ lp.layer = lpp->layer;
+ }
+ }
+
+ } else if (! m_create_layers) {
+ return std::make_pair (false, 0);
+ }
+
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
if ((*l).second->log_equal (lp)) {
return std::make_pair (true, (*l).first);
@@ -1139,8 +1246,6 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
}
}
- // Note: "name" is the decorated name as provided by the tech component's
- // x_suffix specifications.
std::string name_suffix;
int dt = 0;
@@ -1182,8 +1287,10 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
}
}
+ // "name" is the decorated name as provided by the tech component's x_suffix specifications.
std::string name = n + name_suffix;
+ // Assign a layer number (a default one for now) and the datatype from the tech component's x_datatype specification.
db::LayerProperties lp (name);
lp.datatype = dt;
std::map::const_iterator ldef = m_default_number.find (n);
@@ -1191,21 +1298,31 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
lp.layer = ldef->second;
}
+ // Route the layer through the layer map, first the decorated name and if there is no mapping, the
+ // undecorated one.
std::pair ll = m_layer_map.logical (name, layout);
+ bool generic_match = false;
if (! ll.first) {
ll = m_layer_map.logical (n, layout);
+ generic_match = true;
}
if (ll.first) {
+ // If the layer map provides a target, use that one for the layer
+ // Datatypes from the target and the tech component's x_datatype specification are additive
const db::LayerProperties *lpp = m_layer_map.target (ll.second);
if (lpp) {
lp = *lpp;
- if (lp.datatype >= 0) {
+ if (lp.datatype < 0) {
+ lp.datatype = dt;
+ } else if (generic_match) {
lp.datatype += dt;
}
if (lp.name.empty ()) {
lp.name = name;
+ } else if (generic_match) {
+ lp.name += name_suffix;
}
}
@@ -1254,44 +1371,7 @@ LEFDEFReaderState::finish (db::Layout &layout)
continue;
}
- std::string ps;
-
- switch (l->first.second.first) {
- case Outline:
- ps = "OUTLINE";
- break;
- case Regions:
- ps = "REGION";
- break;
- case PlacementBlockage:
- ps = "PLACEMENT_BLK";
- break;
- case Routing:
- default:
- ps = "NET";
- break;
- case SpecialRouting:
- ps = "SPNET";
- break;
- case ViaGeometry:
- ps = "VIA";
- break;
- case Label:
- ps = "LABEL";
- break;
- case Pins:
- ps = "PIN";
- break;
- case LEFPins:
- ps = "LEFPIN";
- break;
- case Obstructions:
- ps = "OBS";
- break;
- case Blockage:
- ps = "BLK";
- break;
- }
+ std::string ps = purpose_to_name (l->first.second.first);
unsigned int layer_index = l->second.second;
db::LayerProperties lp = layout.get_properties (layer_index);
@@ -1336,7 +1416,7 @@ LEFDEFReaderState::finish (db::Layout &layout)
}
- // On return we deliver the "canonical" map
+ // On return we deliver the "canonical" map which lists the decorated name vs. the real ones.
m_layer_map = lm;
}
diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
index 72332bedf..fa446436a 100644
--- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
+++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
@@ -50,16 +50,13 @@ static db::LEFDEFReaderOptions default_options ()
return tc;
}
-static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true)
+static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *filename, const db::LEFDEFReaderOptions &options, bool priv = true)
{
std::string fn_path (priv ? tl::testsrc_private () : tl::testsrc ());
fn_path += "/testdata/lefdef/";
fn_path += lef_dir;
fn_path += "/";
- db::Manager m (false);
- db::Layout layout (&m), layout2 (&m), layout_au (&m);
-
tl::Extractor ex (filename);
db::LEFDEFReaderState ld (&options, layout, fn_path);
@@ -142,6 +139,16 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
ld.finish (layout);
+ return ld.layer_map ();
+}
+
+static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true)
+{
+ db::Manager m (false);
+ db::Layout layout (&m), layout2 (&m), layout_au (&m);
+
+ db::LayerMap lm = read (layout, lef_dir, filename, options, priv);
+
// normalize the layout by writing to OASIS and reading from ..
// generate a "unique" name ...
@@ -200,7 +207,7 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
}
- return ld.layer_map ();
+ return lm;
}
TEST(1)
@@ -549,16 +556,151 @@ TEST(115_componentmaskshift)
run_test (_this, "masks-2", "lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", options, false);
}
-TEST(116_name_to_ld_target_mapping)
+TEST(116_layer_mapping)
{
db::LEFDEFReaderOptions options = default_options ();
db::LayerMap lm = db::LayerMap::from_string_file_format ("metal1: 1\nvia1: 2\nmetal2: 3\nOUTLINE: 42/17");
options.set_layer_map (lm);
- db::LayerMap lm_read = run_test (_this, "via_properties", "lef:in.lef+def:in.def", "au.oas.gz", options, false);
- EXPECT_EQ (lm_read.to_string (),
- "layer_map('OUTLINE : OUTLINE (4/0)';'metal1.VIA : metal1 (1/0)';'metal2.VIA : metal2 (3/0)';'via1.VIA : via1 (2/0)')"
- )
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTLINE (42/17)';'metal1.VIA : metal1 (1/0)';'metal2.VIA : metal2 (3/0)';'via1.VIA : via1 (2/0)')"
+ )
+ }
+
+ options.set_layer_map (db::LayerMap ());
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTLINE (4/0)';'metal1.VIA : metal1 (1/0)';'metal2.VIA : metal2 (3/0)';'via1.VIA : via1 (2/0)')"
+ )
+ }
+
+ lm = db::LayerMap::from_string_file_format ("metal1: M1\nmetal1.V: M1_V\nvia1: V1\nmetal2: M2\nOUTLINE: OUTL");
+ options.set_layer_map (lm);
+ options.set_via_geometry_suffix ("V");
+ options.set_via_geometry_datatype (42);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTL (4/0)';'metal1.VIA : M1V (1/42)';'metal2.VIA : M2V (3/42)';'via1.VIA : V1V (2/42)')"
+ )
+ }
+
+ lm = db::LayerMap::from_string_file_format ("metal1: M1\nmetal1.V: M1_V\nvia1: V1\nmetal2: M2");
+ options.set_layer_map (lm);
+ options.set_via_geometry_suffix ("V");
+ options.set_via_geometry_datatype (42);
+ options.set_read_all_layers (false);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('metal1.VIA : M1V (1/42)';'metal2.VIA : M2V (3/42)';'via1.VIA : V1V (2/42)')"
+ )
+ }
+
+ lm = db::LayerMap::from_string_file_format ("metal2: M2 (17/1)");
+ options.set_layer_map (lm);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('metal2.VIA : M2V (17/43)')"
+ )
+ }
+
+ options.set_produce_via_geometry (false);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map()"
+ )
+ }
+
+ options.set_produce_via_geometry (true);
+ options.set_via_geometry_suffix (".V");
+ lm = db::LayerMap::from_string_file_format ("metal2.V: 17/1");
+ options.set_layer_map (lm);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('metal2.VIA : metal2.V (17/1)')"
+ )
+ }
+
+ lm = db::LayerMap::from_string_file_format ("metal2.V: m2v (17/5)");
+ options.set_layer_map (lm);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('metal2.VIA : m2v (17/5)')"
+ )
+ }
+
+ lm = db::LayerMap::from_string_file_format ("OUTLINE: OUTL");
+ options.set_layer_map (lm);
+ options.set_cell_outline_layer ("OUTLINE (42/17)");
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTL (42/17)')"
+ )
+ }
+
+ lm = db::LayerMap::from_string_file_format ("OUTLINE: OUTL (18/1)");
+ options.set_layer_map (lm);
+ options.set_cell_outline_layer ("OUTLINE (42/17)");
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTL (18/1)')"
+ )
+ }
+
+ options.set_cell_outline_layer ("OUTLINE (42/17)");
+ lm = db::LayerMap::from_string_file_format ("42/17: OUTL (18/1)");
+ options.set_layer_map (lm);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTL (18/1)')"
+ )
+ }
+
+ options.set_cell_outline_layer ("42/17");
+ lm = db::LayerMap::from_string_file_format ("42/17: 18/1");
+ options.set_layer_map (lm);
+
+ {
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "via_properties", "lef:in.lef+def:in.def", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map('OUTLINE : OUTLINE (18/1)')"
+ )
+ }
+
+
}
TEST(200_lefdef_plugin)
From 3b61255d9b718fefdcc0b58735022a34d4ac219e Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 21 Nov 2020 21:06:05 +0100
Subject: [PATCH 04/29] Bugfix, restore previous behavior for empty tech
component suffix
---
src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index 4cc77b69d..2c47e2984 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -1305,6 +1305,9 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
if (! ll.first) {
ll = m_layer_map.logical (n, layout);
generic_match = true;
+ } else if (n == name) {
+ // no suffix defined in tech component -> treat as generic match and combine datatypes
+ generic_match = true;
}
if (ll.first) {
From 96898d31d76ef6fc9244b2b8e65e8db547cfcc6f Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 21 Nov 2020 21:58:34 +0100
Subject: [PATCH 05/29] LEF/DEF layer map reader test case added.
---
.../lefdef/unit_tests/dbLEFDEFImportTests.cc | 16 ++++++++++
testdata/lefdef/mapfile/all.map | 29 +++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 testdata/lefdef/mapfile/all.map
diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
index fa446436a..4e71f6032 100644
--- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
+++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
@@ -699,8 +699,24 @@ TEST(116_layer_mapping)
"layer_map('OUTLINE : OUTLINE (18/1)')"
)
}
+}
+TEST(117_mapfile_all)
+{
+ db::LEFDEFReaderOptions options = default_options ();
+ db::Layout layout;
+ db::LayerMap lm_read = read (layout, "mapfile", "lef:in.lef+def:in.def+map:all.map", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map("
+ "'OUTLINE : OUTLINE (1/0)';"
+ "'M1.BLK;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/...\\' (22/2)';"
+ "'\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';"
+ "'\\'M1.PIN:1\\';\\'M1.SPNET:1\\';\\'M1.VIA:1\\' : \\'M1.NET:1/...\\' (6/0)';"
+ "'M1.LABEL : M1.LABEL (28/1)';"
+ "'M1_TEXT.LABEL : M1_TEXT.LABEL (29/0)'"
+ ")"
+ )
}
TEST(200_lefdef_plugin)
diff --git a/testdata/lefdef/mapfile/all.map b/testdata/lefdef/mapfile/all.map
new file mode 100644
index 000000000..3a12f0952
--- /dev/null
+++ b/testdata/lefdef/mapfile/all.map
@@ -0,0 +1,29 @@
+# some variations of map file entries
+DIEAREA ALL 1 0
+COMP ALL 2 0
+M1 PIN 3,4 0
+M1 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA1 5
+M1 NET,SPNET,PIN,VIA:MASK:1 6 0
+M1 NET:MASK:1 7 0
+M1 TEXT 8 0
+M1 FILLOPC 9 0
+M1 FILLOPC:MASK:1 10 0
+M1 FILLOPC:MASK:2 11 0
+M1 BLOCKAGEFILL 12 0
+M1 BLOCKAGE 13 0
+M1 FILL 14 0
+M1 VIAFILL,FILL 15 0
+M1 NET,SPNET,CUSTOM 16 0
+M1 VIAFILL:FLOATING,FILL:FLOATING 17 0
+M1 NET:VOLTAGE:0.8 18 0
+M1 VIAFILL 19 0
+M1 VIA:SIZE:0.05x0.05 20 0
+M1 VIA:SIZE:3x3 21 0
+M1 ALL 22 2
+NAME DIEAREA 23 0
+NAME ALL 24 0
+NAME COMP 25 0
+NAME M1/PIN 26 0
+NAME M1/NET 27 0
+NAME M1/SPNET 28 1
+NAME M1_TEXT 29 0
From 363c437d0737d2b73ce73ee8b361f2c38a330865 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 21 Nov 2020 22:05:10 +0100
Subject: [PATCH 06/29] Updated testcase for LEF/DEF map file reader
---
testdata/lefdef/mapfile/all.map | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/testdata/lefdef/mapfile/all.map b/testdata/lefdef/mapfile/all.map
index 3a12f0952..462c62ea3 100644
--- a/testdata/lefdef/mapfile/all.map
+++ b/testdata/lefdef/mapfile/all.map
@@ -2,7 +2,8 @@
DIEAREA ALL 1 0
COMP ALL 2 0
M1 PIN 3,4 0
-M1 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA1 5
+M1 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 1 5
+DOES NOT MEAN ANYTHING
M1 NET,SPNET,PIN,VIA:MASK:1 6 0
M1 NET:MASK:1 7 0
M1 TEXT 8 0
From 85311d414c99865e3b0e570b15566d2bda0d8764 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 14 Dec 2020 22:20:29 +0100
Subject: [PATCH 07/29] Implemented LEF DENSITY statement properly
---
.../lefdef/db_plugin/dbLEFImporter.cc | 18 ++++++++++++
.../lefdef/unit_tests/dbLEFDEFImportTests.cc | 6 ++++
testdata/lefdef/density/.in.lef.swp | Bin 0 -> 12288 bytes
testdata/lefdef/density/au.oas.gz | Bin 0 -> 493 bytes
testdata/lefdef/density/in.lef | 27 ++++++++++++++++++
5 files changed, 51 insertions(+)
create mode 100644 testdata/lefdef/density/.in.lef.swp
create mode 100644 testdata/lefdef/density/au.oas.gz
create mode 100644 testdata/lefdef/density/in.lef
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc
index c1a6caa1c..00be1e947 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc
@@ -937,6 +937,24 @@ LEFImporter::read_macro (Layout &layout)
expect ("END");
+ } else if (test ("DENSITY")) {
+
+ // read over DENSITY statements
+ while (! test ("END")) {
+ if (test ("LAYER")) {
+ get ();
+ expect (";");
+ } else {
+ expect ("RECT");
+ for (int i = 0; i < 5; ++i) {
+ get_double ();
+ }
+ expect (";");
+ }
+ }
+
+ expect ("END");
+
} else if (test ("FIXEDMASK")) {
mg->set_fixedmask (true);
diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
index 4e71f6032..c46067119 100644
--- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
+++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
@@ -719,6 +719,11 @@ TEST(117_mapfile_all)
)
}
+TEST(118_density)
+{
+ run_test (_this, "density", "read:in.lef", "au.oas.gz", default_options (), false);
+}
+
TEST(200_lefdef_plugin)
{
db::Layout ly;
@@ -764,3 +769,4 @@ TEST(201_lefdef_plugin_explicit_lef)
db::compare_layouts (_this, ly, fn_path + "au_plugin_alt_lef.oas.gz", db::WriteOAS);
}
+
diff --git a/testdata/lefdef/density/.in.lef.swp b/testdata/lefdef/density/.in.lef.swp
new file mode 100644
index 0000000000000000000000000000000000000000..b3c13c94dad2bd3db908b980f22d02d0971a1a55
GIT binary patch
literal 12288
zcmeI2O=}ZD9L6Vl@F1PPUd+o97xJRJn@U8Gt=Z6E(u8DkD2n|E
zdhrW*@$Aiu9=!A>2x2|y&95MM@|oRDv=Ne%g7P1DW_D+ud1mIfdkNWHv13?N-p%TfzRQBMzJ{I!sWeOkh`>SuW7*!!EwPko2<2T{z05COXe^vY
z1|mQNhyW2F0z`la5CI}U1pXfaa*$w$IL@i~NSER^G1JDk)DQt8Km>>Y5g-CYfCvx)
zB0vO)01+Sp{~!Us#n`na#@<5e|NqJF|8M8;EdcZd`T!k4Z=l!EOXxZD1bPUKp<9p!
ztw7(G89RpFLr2gn=qYpv8PI2}^$B_xuloY+Bgli2&>Y5g-CYfCvx)
zBJfuUShW(b*aau=G#RdEZn^qQIbfWlAGIouRrI*{1HL(tbB0*Bsc2V*5L|E*wYo~1
zn#s5M+Az2;d3)IJ@pW`3#Rivsz7AJX**22l8SyDL@3+G_SALCDfhsHv%xIaJz-gRH
z{yhy7qO?lBX*qny&KrFDM7$=_TxenoRW_@tTt=;>iP#rStVYxDbX?nOB4GA$XeQKE_pZL6rhAX)(b9b
z*S=$+?{@wh!N?Dtm#
literal 0
HcmV?d00001
diff --git a/testdata/lefdef/density/au.oas.gz b/testdata/lefdef/density/au.oas.gz
new file mode 100644
index 0000000000000000000000000000000000000000..c24d3412bf8b64b14b65e78f20b85a8b7fc7e7ac
GIT binary patch
literal 493
zcmY!lcJ=kt^>+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I
zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>u%@Ku6{j*oC~kKD&=4O_KUZdEW(FQ)
z4mX>xp`O1}Ff$`FGY=A*n
Date: Mon, 14 Dec 2020 22:46:07 +0100
Subject: [PATCH 08/29] LEF/DEF reader: Macro resolution mode is only effective
now when reading DEF. Not when reading LEF.
---
.../lefdef/db_plugin/dbLEFDEFImporter.h | 2 +-
.../lefdef/db_plugin/dbLEFDEFPlugin.cc | 21 ++++++++++--------
.../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 6 ++---
.../LEFDEFTechnologyComponentEditor.ui | 4 +++-
testdata/lefdef/density/.in.lef.swp | Bin 12288 -> 0 bytes
testdata/lefdef/density/in.lef | 1 +
6 files changed, 20 insertions(+), 14 deletions(-)
delete mode 100644 testdata/lefdef/density/.in.lef.swp
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
index ec1da4076..078361d33 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
@@ -775,7 +775,7 @@ public:
}
/**
- * @brief Specify the LEF macro resolution strategy
+ * @brief Specify the LEF macro resolution strategy when reading DEF files
* Values are:
* 0: propduce LEF geometry unless a FOREIGN cell is specified (default)
* 1: produce LEF geometry always and ignore FOREIGN
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc
index c874ab814..470e87d19 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc
@@ -113,22 +113,25 @@ private:
const db::LayerMap &read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef)
{
const db::LEFDEFReaderOptions *lefdef_options = dynamic_cast (options.get_options (format ()));
- static db::LEFDEFReaderOptions default_options;
- if (! lefdef_options) {
- lefdef_options = &default_options;
+ db::LEFDEFReaderOptions effective_options;
+ if (lefdef_options) {
+ effective_options = *lefdef_options;
}
- db::LEFDEFReaderState state (lefdef_options, layout, tl::dirname (m_stream.absolute_path ()));
+ db::LEFDEFReaderState state (&effective_options, layout, tl::dirname (m_stream.absolute_path ()));
- layout.dbu (lefdef_options->dbu ());
+ layout.dbu (effective_options.dbu ());
if (import_lef) {
+ // Always produce LEF geometry when reading LEF
+ effective_options.set_macro_resolution_mode (1);
+
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
db::LEFImporter importer;
- for (std::vector::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) {
+ for (std::vector::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
@@ -149,7 +152,7 @@ private:
DEFImporter importer;
- for (std::vector::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) {
+ for (std::vector::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
@@ -163,7 +166,7 @@ private:
// Additionally read all LEF files next to the DEF file
- if (lefdef_options->read_lef_with_def ()) {
+ if (effective_options.read_lef_with_def ()) {
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
@@ -198,7 +201,7 @@ private:
std::map foreign_cells = state.foreign_cells ();
db::cell_index_type seen = std::numeric_limits::max ();
- std::vector macro_layouts = lefdef_options->macro_layouts ();
+ std::vector macro_layouts = effective_options.macro_layouts ();
for (std::vector::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) {
std::vector target_cells, source_cells;
diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc
index b86a4fd21..2643028f6 100644
--- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc
@@ -770,8 +770,8 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_resolution_mode", &db::LEFDEFReaderOptions::macro_resolution_mode,
- "@brief Gets the macro resolution mode.\n"
- "This property describes the way LEF macros are turned into GDS cells. There "
+ "@brief Gets the macro resolution mode (LEF macros into DEF).\n"
+ "This property describes the way LEF macros are turned into layout cells when reading DEF. There "
"are three modes available:\n"
"\n"
"@ul\n"
@@ -786,7 +786,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"),
- "@brief Sets the macro resolution mode.\n"
+ "@brief Sets the macro resolution mode (LEF macros into DEF).\n"
"See \\macro_resolution_mode for details about this property.\n"
"\n"
"This property has been added in version 0.27.\n"
diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui
index 18825ffa5..73212cb25 100644
--- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui
+++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui
@@ -294,7 +294,7 @@
-
- LEF import
+ LEF import into DEF
@@ -708,6 +708,8 @@
If a layer map file is given, pattern based rules are ignored.
If used inside a technology, the file will be looked up relative to the technology's base path.
+Otherwise it's looked up relative to the LEF or DEF file.
+
(2*) Die area, Blockage and Region layers in map file will have priority over global production rules above.
diff --git a/testdata/lefdef/density/.in.lef.swp b/testdata/lefdef/density/.in.lef.swp
deleted file mode 100644
index b3c13c94dad2bd3db908b980f22d02d0971a1a55..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 12288
zcmeI2O=}ZD9L6Vl@F1PPUd+o97xJRJn@U8Gt=Z6E(u8DkD2n|E
zdhrW*@$Aiu9=!A>2x2|y&95MM@|oRDv=Ne%g7P1DW_D+ud1mIfdkNWHv13?N-p%TfzRQBMzJ{I!sWeOkh`>SuW7*!!EwPko2<2T{z05COXe^vY
z1|mQNhyW2F0z`la5CI}U1pXfaa*$w$IL@i~NSER^G1JDk)DQt8Km>>Y5g-CYfCvx)
zB0vO)01+Sp{~!Us#n`na#@<5e|NqJF|8M8;EdcZd`T!k4Z=l!EOXxZD1bPUKp<9p!
ztw7(G89RpFLr2gn=qYpv8PI2}^$B_xuloY+Bgli2&>Y5g-CYfCvx)
zBJfuUShW(b*aau=G#RdEZn^qQIbfWlAGIouRrI*{1HL(tbB0*Bsc2V*5L|E*wYo~1
zn#s5M+Az2;d3)IJ@pW`3#Rivsz7AJX**22l8SyDL@3+G_SALCDfhsHv%xIaJz-gRH
z{yhy7qO?lBX*qny&KrFDM7$=_TxenoRW_@tTt=;>iP#rStVYxDbX?nOB4GA$XeQKE_pZL6rhAX)(b9b
z*S=$+?{@wh!N?Dtm#
diff --git a/testdata/lefdef/density/in.lef b/testdata/lefdef/density/in.lef
index 889d5763d..abc0ccbf6 100644
--- a/testdata/lefdef/density/in.lef
+++ b/testdata/lefdef/density/in.lef
@@ -8,6 +8,7 @@ END VIA1
MACRO dense
CLASS CORE ;
ORIGIN 0.0 0.0 ;
+ FOREIGN dense ;
SIZE 0.7 BY 0.9 ;
OBS
LAYER M1 DESIGNRULEWIDTH 0.05 ;
From 1106a52688b22b1207379503cf96818423a31d97 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Mon, 14 Dec 2020 23:55:04 +0100
Subject: [PATCH 09/29] WIP: first draft of implementation
---
src/db/db/dbStreamLayers.cc | 268 +++++++++++++++++++++++++++---------
src/db/db/dbStreamLayers.h | 69 ++++++++--
2 files changed, 262 insertions(+), 75 deletions(-)
diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc
index fb33f3ac7..f73d3dc11 100644
--- a/src/db/db/dbStreamLayers.cc
+++ b/src/db/db/dbStreamLayers.cc
@@ -40,10 +40,9 @@ namespace db
/// A helper class to join two datatype map members
struct LmapJoinOp1
{
- void operator() (unsigned int &a, unsigned int b)
+ void operator() (std::set &a, const std::set &b)
{
- // TODO: could also do?: throw an exception ..
- a = b;
+ a.insert (b.begin (), b.end ());
}
};
@@ -58,7 +57,27 @@ struct LmapJoinOp2
}
};
-/// Utility typedefs for the expression parser
+/// A helper class to implement the unmap operation
+struct LmapEraseDatatypeInterval
+{
+ LmapEraseDatatypeInterval (unsigned int dfrom, unsigned int dto)
+ : m_dfrom (dfrom), m_dto (dto)
+ { }
+
+ void operator() (LayerMap::datatype_map &a, const LayerMap::datatype_map &)
+ {
+ if (is_static_ld (m_dfrom) && is_static_ld (m_dto)) {
+ a.erase (m_dfrom, m_dto);
+ } else {
+ a.clear ();
+ }
+ }
+
+private:
+ unsigned int m_dfrom, m_dto;
+};
+
+/// Utility typedefs for the expression parser
typedef std::pair ld_interval;
/// Utility typedefs for the expression parser
@@ -71,70 +90,70 @@ LayerMap::LayerMap ()
// .. nothing yet ..
}
-std::pair
+std::set
LayerMap::logical (const LDPair &p) const
{
return logical_internal (p, false);
}
-std::pair
+std::set
LayerMap::logical (const std::string &n) const
{
return logical_internal (n, false);
}
-std::pair
+std::set
LayerMap::logical (const db::LayerProperties &p) const
{
return logical_internal (p, false);
}
-std::pair
+std::set
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);
+ const std::set *l = dm->mapped (p.datatype);
if (l && (allow_placeholder || ! is_placeholder (*l))) {
- return std::make_pair (true, *l);
+ return *l;
}
}
- return std::make_pair (false, 0);
+ return std::set ();
}
-std::pair
+std::set
LayerMap::logical_internal (const std::string &n, bool allow_placeholder) const
{
- std::map::const_iterator m = m_name_map.find (n);
+ std::map >::const_iterator m = m_name_map.find (n);
if (m != m_name_map.end () && (allow_placeholder || ! is_placeholder (m->second))) {
- return std::make_pair (true, m->second);
+ return m->second;
} else {
- return std::make_pair (false, 0);
+ return std::set ();
}
}
-std::pair
+std::set
LayerMap::logical_internal (const db::LayerProperties &p, bool allow_placeholder) const
{
+ std::set m;
if (p.layer >= 0 && p.datatype >= 0) {
- std::pair m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
- if (m.first) {
- return m;
- }
+ m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
}
- if (! p.name.empty ()) {
- std::pair m = logical_internal (p.name, allow_placeholder);
- if (m.first) {
- return m;
- }
+ if (m.empty () && ! p.name.empty ()) {
+ m = logical_internal (p.name, allow_placeholder);
}
- return std::make_pair (false, 0);
+ return m;
}
bool
-LayerMap::is_placeholder (unsigned int l) const
+LayerMap::is_placeholder (const std::set &m) const
{
- return (m_placeholders.size () > std::numeric_limits::max () - l);
+ for (std::set::const_iterator i = m.begin (); i != m.end (); ++i) {
+ if (m_placeholders.size () > std::numeric_limits::max () - *i) {
+ return true;
+ }
+ }
+ return false;
}
const db::LayerProperties *
@@ -148,39 +167,52 @@ LayerMap::target (unsigned int l) const
}
}
-std::pair
+std::set
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);
+ std::set l = logical_internal (p, true);
+ if (is_placeholder (l)) {
+ return const_cast (this)->substitute_placeholder (p, l, layout);
} else {
return l;
}
}
-std::pair
+std::set
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);
+ std::set l = logical_internal (p, true);
+ if (is_placeholder (l)) {
+ return const_cast (this)->substitute_placeholder (db::LayerProperties (p.layer, p.datatype), l, layout);
} else {
return l;
}
}
-std::pair
-LayerMap::substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout)
+std::set
+LayerMap::substitute_placeholder (const db::LayerProperties &p, const std::set &m, 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);
+ std::set res;
+ for (std::set::const_iterator i = m.begin (); i != m.end (); ++i) {
- unsigned int l_new = layout.insert_layer (lp_new);
- map (p, l_new, lp_new);
- return std::make_pair (true, l_new);
+ if (m_placeholders.size () > std::numeric_limits::max () - *i) {
+
+ const db::LayerProperties &lp_ph = m_placeholders [std::numeric_limits::max () - *i];
+ 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);
+ res.insert (l_new);
+
+ } else {
+ res.insert (*i);
+ }
+
+ }
+
+ return res;
}
static std::string format_interval (ld_type l1, ld_type l2)
@@ -206,7 +238,7 @@ LayerMap::mapping_str (unsigned int ll) const
bool f2 = true;
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
- if (d->second == ll) {
+ if (d->second.find (ll) != d->second.end ()) {
// create a string representation
if (!f2) {
@@ -232,8 +264,9 @@ LayerMap::mapping_str (unsigned int ll) const
}
- for (std::map ::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
- if (l->second == ll) {
+ for (std::map >::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
+
+ if (l->second.find (ll) != l->second.end ()) {
if (!f1) {
s += ";";
@@ -243,6 +276,7 @@ LayerMap::mapping_str (unsigned int ll) const
s += tl::to_word_or_quoted_string (l->first);
}
+
}
std::map::const_iterator t = m_target_layers.find (ll);
@@ -300,11 +334,19 @@ LayerMap::prepare (db::Layout &layout)
// Now remap the indexes
for (ld_map::iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
for (datatype_map::iterator d = l->second.begin (); d != l->second.end (); ++d) {
- d->second = real_layers [d->second];
+ std::set dn;
+ for (std::set::const_iterator i = d->second.begin (); i != d->second.end (); ++i) {
+ dn.insert (real_layers [*i]);
+ }
+ d->second = dn;
}
}
- for (std::map::iterator n = m_name_map.begin (); n != m_name_map.end (); ++n) {
- n->second = real_layers [n->second];
+ for (std::map >::iterator n = m_name_map.begin (); n != m_name_map.end (); ++n) {
+ std::set dn;
+ for (std::set::const_iterator i = n->second.begin (); i != n->second.end (); ++i) {
+ dn.insert (real_layers [*i]);
+ }
+ n->second = dn;
}
std::map old_target_layers;
@@ -329,11 +371,11 @@ LayerMap::get_layers () const
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) {
- layers.insert (d->second);
+ layers.insert (d->second.begin (), d->second.end ());
}
}
for (const_iterator_names n = m_name_map.begin (); n != m_name_map.end (); ++n) {
- layers.insert(n->second);
+ layers.insert(n->second.begin (), n->second.end ());
}
return std::vector (layers.begin (), layers.end ());
@@ -358,7 +400,7 @@ LayerMap::mapping (unsigned int ll) const
// 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) {
+ if (d->second.find (ll) != d->second.end ()) {
p.layer = l->first.first;
p.datatype = d->first.first;
break;
@@ -373,7 +415,7 @@ LayerMap::mapping (unsigned int ll) const
// 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) {
+ if (d->second.find (ll) != d->second.end ()) {
p.layer = l->first.first;
p.datatype = d->first.first;
break;
@@ -384,8 +426,8 @@ LayerMap::mapping (unsigned int ll) const
}
if (p.name.empty ()) {
- for (std::map ::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
- if (l->second == ll) {
+ for (std::map >::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
+ if (l->second.find (ll) != l->second.end ()) {
p.name = l->first;
break;
}
@@ -515,7 +557,7 @@ LayerMap::map_expr (tl::Extractor &ex, unsigned int l)
ld_type n;
if (! ex.try_read (n) && ex.try_read_word_or_quoted (name)) {
- m_name_map.insert (std::make_pair (name, l));
+ m_name_map [name].insert (l);
} else {
@@ -533,7 +575,9 @@ LayerMap::map_expr (tl::Extractor &ex, unsigned int l)
datatype_map dm;
for (ld_interval_vector::const_iterator di = vd.begin (); di != vd.end (); ++di) {
LmapJoinOp1 op1;
- dm.add (di->first, di->second + 1, l, op1);
+ std::set single;
+ single.insert (l);
+ dm.add (di->first, di->second + 1, single, op1);
}
for (ld_interval_vector::const_iterator li = vl.begin (); li != vl.end (); ++li) {
LmapJoinOp2 op2;
@@ -566,7 +610,7 @@ LayerMap::insert (const std::string &name, unsigned int l, const LayerProperties
m_target_layers[l] = *target;
}
- m_name_map.insert (std::make_pair (name, l));
+ m_name_map [name].insert (l);
if (l >= m_next_index) {
m_next_index = l + 1;
@@ -580,13 +624,16 @@ LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const Laye
m_target_layers[l] = *target;
}
+ std::set single;
+ single.insert (l);
+
// create a single-interval list for the datatype range
LayerMap::datatype_map dt;
LmapJoinOp1 op1;
if (db::is_static_ld (p1.datatype) && db::is_static_ld (p2.datatype)) {
- dt.add (p1.datatype, p2.datatype + 1, l, op1);
+ dt.add (p1.datatype, p2.datatype + 1, single, op1);
} else {
- dt.add (0, std::numeric_limits::max (), l, op1);
+ dt.add (0, std::numeric_limits::max (), single, op1);
}
// add this to the layers using the special join operator that
@@ -603,6 +650,103 @@ LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const Laye
}
}
+void
+LayerMap::unmap (const LDPair &f)
+{
+ unmap (f, f);
+}
+
+void
+LayerMap::unmap (const std::string &name)
+{
+ m_name_map.erase (name);
+}
+
+void
+LayerMap::unmap (const LayerProperties &f)
+{
+ if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
+ unmap (db::LDPair (f.layer, f.datatype));
+ }
+ if (! f.name.empty ()) {
+ unmap (f.name);
+ }
+}
+
+
+
+void
+LayerMap::unmap (const LDPair &p1, const LDPair &p2)
+{
+ if (m_ld_map.begin () == m_ld_map.end ()) {
+ return;
+ }
+
+ LmapEraseDatatypeInterval op (p1.datatype, p2.datatype);
+ if (db::is_static_ld (p1.layer) && db::is_static_ld (p2.layer)) {
+ m_ld_map.add (p1.layer, p1.layer + 1, LayerMap::datatype_map (), op);
+ } else {
+ m_ld_map.add (m_ld_map.begin ()->first.first, m_ld_map.end ()->first.second, LayerMap::datatype_map (), op);
+ }
+}
+
+void
+LayerMap::unmap_expr (const std::string &expr)
+{
+ tl::Extractor ex (expr.c_str ());
+ unmap_expr (ex);
+ ex.expect_end ();
+}
+
+void
+LayerMap::unmap_expr (tl::Extractor &ex)
+{
+ try {
+
+ do {
+
+ tl::Extractor ex_saved = ex;
+
+ std::string name;
+ ld_type n;
+ if (! ex.try_read (n) && ex.try_read_word_or_quoted (name)) {
+
+ m_name_map.erase (name);
+
+ } else {
+
+ ex = ex_saved;
+ ld_interval_vector vl, vd;
+
+ parse_intervals (ex, vl);
+
+ if (ex.test ("/")) {
+ parse_intervals (ex, vd);
+ } else {
+ vd.push_back (ld_interval (0, 0));
+ }
+
+ for (ld_interval_vector::const_iterator li = vl.begin (); li != vl.end (); ++li) {
+ for (ld_interval_vector::const_iterator di = vd.begin (); di != vd.end (); ++di) {
+ unmap (LDPair (li->first, di->first), LDPair (li->second, di->second));
+ }
+ }
+
+ }
+
+ } while (ex.test (";") || ex.test (","));
+
+ if (ex.test (":")) {
+ // ignore target layers
+ LayerProperties lp;
+ lp.read (ex, true);
+ }
+
+ } catch (...) {
+ throw LayerSpecFormatException (ex.skip ());
+ }
+}
+
void
LayerMap::clear ()
{
diff --git a/src/db/db/dbStreamLayers.h b/src/db/db/dbStreamLayers.h
index b142d7d95..8ea0d78b5 100644
--- a/src/db/db/dbStreamLayers.h
+++ b/src/db/db/dbStreamLayers.h
@@ -35,6 +35,7 @@
#include
@@ -29,6 +29,19 @@
6
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Load File
+
+
+
-
@@ -45,103 +58,114 @@
- -
-
-
-
- 0
- 0
-
-
-
- Load File
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- true
-
-
- QAbstractItemView::InternalMove
-
-
- QAbstractItemView::ExtendedSelection
-
-
- true
-
-
- false
-
-
-
- -
-
-
- Add a new layer to the list
-
-
- Add
-
-
-
- :/add.png:/add.png
-
-
-
- -
-
-
- Delete the selected layers from the list
-
-
- Delete
-
-
-
- :/clear.png:/clear.png
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 5
-
-
-
-
- -
-
-
- Edit the current layer
-
-
- Edit
-
-
-
- :/edit.png:/edit.png
+
-
+
+
+ 1
+
+
+ List
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ true
+
+
+ QAbstractItemView::InternalMove
+
+
+ QAbstractItemView::ExtendedSelection
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
+ Add a new layer to the list
+
+
+ Add
+
+
+
+ :/add.png:/add.png
+
+
+
+ -
+
+
+ Delete the selected layers from the list
+
+
+ Delete
+
+
+
+ :/clear.png:/clear.png
+
+
+
+ -
+
+
+ Edit the current layer
+
+
+ Edit
+
+
+
+ :/edit.png:/edit.png
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 5
+
+
+
+
+
+
+
+
+ Text
+
+
+ -
+
+
+
+
-
+
diff --git a/src/laybasic/laybasic/layLayerMappingWidget.cc b/src/laybasic/laybasic/layLayerMappingWidget.cc
index c5c243e77..e14dadcc7 100644
--- a/src/laybasic/laybasic/layLayerMappingWidget.cc
+++ b/src/laybasic/laybasic/layLayerMappingWidget.cc
@@ -53,6 +53,8 @@ LayerMappingWidget::LayerMappingWidget (QWidget *parent)
mp_ui->layer_lv->viewport ()->acceptDrops ();
+ connect (mp_ui->tabs, SIGNAL (currentChanged (int)), this, SLOT (current_tab_changed (int)));
+
mp_layer_table_file_dialog = new lay::FileDialog (this,
tl::to_string (QObject::tr ("Load Layer Table")),
tl::to_string (QObject::tr ("Layer properties and text files (*.lyp *.txt);;Layer properties files (*.lyp);;Text files (*.txt);;All files (*)")));
@@ -72,6 +74,8 @@ LayerMappingWidget::set_layer_map (const db::LayerMap &lm)
{
std::vector layer_ids = lm.get_layers ();
+ mp_ui->text_edit->setPlainText (tl::to_qstring (lm.to_string_file_format ()));
+
mp_ui->layer_lv->reset ();
mp_ui->layer_lv->clear ();
@@ -88,16 +92,31 @@ LayerMappingWidget::set_layer_map (const db::LayerMap &lm)
db::LayerMap
LayerMappingWidget::get_layer_map () const
+{
+ return get_layer_map_from_tab (mp_ui->tabs->currentIndex ());
+}
+
+db::LayerMap
+LayerMappingWidget::get_layer_map_from_tab (int tab) const
{
db::LayerMap lm;
- for (int i = 0; i < mp_ui->layer_lv->count (); ++i) {
- std::string t = tl::to_string (mp_ui->layer_lv->item (i)->data (Qt::DisplayRole).toString ());
- try {
- lm.map_expr (t, (unsigned int) i);
- } catch (...) {
- mp_ui->layer_lv->setCurrentItem (mp_ui->layer_lv->item (i));
- throw;
+
+ if (tab == 0) {
+
+ for (int i = 0; i < mp_ui->layer_lv->count (); ++i) {
+ std::string t = tl::to_string (mp_ui->layer_lv->item (i)->data (Qt::DisplayRole).toString ());
+ try {
+ lm.add_expr (t, (unsigned int) i);
+ } catch (...) {
+ mp_ui->layer_lv->setCurrentItem (mp_ui->layer_lv->item (i));
+ throw;
+ }
}
+
+ } else {
+
+ lm = db::LayerMap::from_string_file_format (tl::to_string (mp_ui->text_edit->toPlainText ()));
+
}
return lm;
@@ -128,17 +147,19 @@ LayerMappingWidget::load_button_pressed ()
mp_ui->layer_lv->reset ();
mp_ui->layer_lv->clear ();
+ db::LayerMap lm;
+
// use those layers which have cellview index 0
+ unsigned int n = 0;
for (LayerPropertiesConstIterator lay_iter = props.begin_const_recursive (); ! lay_iter.at_end (); ++lay_iter) {
if (! lay_iter->has_children () && lay_iter->source (true /*=real*/).cv_index () == 0) {
db::LayerProperties db_lp = lay_iter->source (true /*=real*/).layer_props ();
- QListWidgetItem *item = new QListWidgetItem (mp_ui->layer_lv);
- item->setData (Qt::DisplayRole, tl::to_qstring (db_lp.to_string ()));
- item->setFlags (item->flags () | Qt::ItemIsEditable);
- mp_ui->layer_lv->addItem (item);
+ lm.map (db_lp, (unsigned int) n++);
}
}
+ set_layer_map (lm);
+
// if successful, stop now.
success = true;
@@ -230,5 +251,11 @@ LayerMappingWidget::edit_button_pressed ()
END_PROTECTED
}
+void
+LayerMappingWidget::current_tab_changed (int index)
+{
+ set_layer_map (get_layer_map_from_tab (1 - index));
+}
+
}
diff --git a/src/laybasic/laybasic/layLayerMappingWidget.h b/src/laybasic/laybasic/layLayerMappingWidget.h
index 9252e8bb7..4c0bac3a4 100644
--- a/src/laybasic/laybasic/layLayerMappingWidget.h
+++ b/src/laybasic/laybasic/layLayerMappingWidget.h
@@ -84,11 +84,14 @@ private slots:
void add_button_pressed ();
void delete_button_pressed ();
void edit_button_pressed ();
+ void current_tab_changed (int tab);
private:
lay::FileDialog *mp_layer_table_file_dialog;
std::string m_layer_table_file;
Ui::LayerMappingWidget *mp_ui;
+
+ db::LayerMap get_layer_map_from_tab (int tab) const;
};
} // namespace lay
From 5bd1cb8bd72fb83c988868d687c3d99904c44d75 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Wed, 16 Dec 2020 23:54:57 +0100
Subject: [PATCH 15/29] WIP: making list the default for layer mapping edit
widget
---
src/laybasic/laybasic/LayerMappingWidget.ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/laybasic/laybasic/LayerMappingWidget.ui b/src/laybasic/laybasic/LayerMappingWidget.ui
index 5fd4d65d7..03855fa9a 100644
--- a/src/laybasic/laybasic/LayerMappingWidget.ui
+++ b/src/laybasic/laybasic/LayerMappingWidget.ui
@@ -61,7 +61,7 @@
-
- 1
+ 0
From 3fbfb2072766efcb4d3778d143dbc263c0ae838f Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 00:56:45 +0100
Subject: [PATCH 16/29] WIP: shorter mapping strings.
---
src/db/db/dbStreamLayers.cc | 82 ++++++++++++++++++-------
src/db/unit_tests/dbStreamLayerTests.cc | 20 +++---
src/lay/lay/doc/about/layer_mapping.xml | 28 +++++++++
3 files changed, 98 insertions(+), 32 deletions(-)
diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc
index eb1260601..ac2cc9819 100644
--- a/src/db/db/dbStreamLayers.cc
+++ b/src/db/db/dbStreamLayers.cc
@@ -262,6 +262,43 @@ static std::string format_interval (ld_type l1, ld_type l2)
}
}
+static std::vector >
+extract_dt_intervals (const LayerMap::datatype_map &dt_map, int ll, bool &has_others)
+{
+ std::vector > res;
+
+ for (LayerMap::datatype_map::const_iterator d = dt_map.begin (); d != dt_map.end (); ) {
+
+ if (d->second.find (ll) != d->second.end ()) {
+
+ std::pair dpi = d->first;
+
+ if (d->second.size () > 1) {
+ has_others = true;
+ }
+
+ LayerMap::datatype_map::const_iterator dd = d;
+ ++dd;
+ while (dd != dt_map.end () && dd->first.first == dpi.second && dd->second.find (ll) != dd->second.end ()) {
+ if (dd->second.size () > 1) {
+ has_others = true;
+ }
+ dpi.second = dd->first.second;
+ ++dd;
+ }
+
+ d = dd;
+
+ res.push_back (dpi);
+
+ } else {
+ ++d;
+ }
+
+ }
+ return res;
+}
+
std::string
LayerMap::mapping_str (unsigned int ll) const
{
@@ -269,36 +306,37 @@ LayerMap::mapping_str (unsigned int ll) const
bool f1 = true;
bool is_mmap = false;
- for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
+ for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ) {
+
+ std::pair lti = l->first;
+
+ std::vector > dti = extract_dt_intervals (l->second, ll, is_mmap);
+ ++l;
+ while (l != m_ld_map.end () && lti.second == l->first.first && extract_dt_intervals (l->second, ll, is_mmap) == dti) {
+ lti.second = l->first.second;
+ ++l;
+ }
bool f2 = true;
- for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
+ for (std::vector >::const_iterator d = dti.begin (); d != dti.end (); ++d) {
- if (d->second.find (ll) != d->second.end ()) {
+ // create a string representation
+ if (!f2) {
+ s += ",";
+ } else {
- if (d->second.size () > 1) {
- is_mmap = true;
+ if (!f1) {
+ s += ";";
}
+ f1 = false;
- // create a string representation
- if (!f2) {
- s += ",";
- } else {
-
- if (!f1) {
- s += ";";
- }
- f1 = false;
-
- s += format_interval (l->first.first, l->first.second);
- s += "/";
-
- }
- f2 = false;
-
- s += format_interval (d->first.first, d->first.second);
+ s += format_interval (lti.first, lti.second);
+ s += "/";
}
+ f2 = false;
+
+ s += format_interval (d->first, d->second);
}
diff --git a/src/db/unit_tests/dbStreamLayerTests.cc b/src/db/unit_tests/dbStreamLayerTests.cc
index 6b0b478b0..f031de1f3 100644
--- a/src/db/unit_tests/dbStreamLayerTests.cc
+++ b/src/db/unit_tests/dbStreamLayerTests.cc
@@ -38,7 +38,7 @@ TEST(1)
EXPECT_EQ (lm.first_logical (db::LDPair (2, 0)).second, (unsigned int) 18);
EXPECT_EQ (lm.first_logical (db::LDPair (0, 0)).first, false);
- EXPECT_EQ (lm.mapping_str (18), "1/0;2-5/0");
+ EXPECT_EQ (lm.mapping_str (18), "1-5/0");
EXPECT_EQ (lm.mapping_str (17), "1/5");
lm.map (db::LDPair (2, 2), 18);
@@ -477,7 +477,7 @@ TEST(8)
// some
lm.mmap_expr ("*/1-10", n++);
EXPECT_EQ (lm.to_string (),
- "layer_map('+*/0,1-10,11-*';'+*/1-10')"
+ "layer_map('+*/*';'+*/1-10')"
);
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
@@ -485,7 +485,7 @@ TEST(8)
lm.mmap_expr ("*/5,15", n++);
EXPECT_EQ (lm.to_string (),
- "layer_map('+*/0,1-4,5,6-10,11-14,15,16-*';'+*/1-4,5,6-10';'+*/5,15')"
+ "layer_map('+*/*';'+*/1-10';'+*/5,15')"
);
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
@@ -496,8 +496,8 @@ TEST(8)
EXPECT_EQ (set2string (lm.logical (db::LDPair (0, 10))), "0,1");
// NOTE: the leading "+" indicates that the listed layers may go somewhere else, so we can't plainly map them
- EXPECT_EQ (lm.mapping_str (0), "+*/0,1-4,5,6-10,11-14,15,16-*");
- EXPECT_EQ (lm.mapping_str (1), "+*/1-4,5,6-10");
+ EXPECT_EQ (lm.mapping_str (0), "+*/*");
+ EXPECT_EQ (lm.mapping_str (1), "+*/1-10");
EXPECT_EQ (lm.mapping_str (2), "+*/5,15");
EXPECT_EQ (lm.mapping_str (3), "");
@@ -516,7 +516,7 @@ TEST(8)
// some
lm.mmap_expr ("1-10/*", n++);
EXPECT_EQ (lm.to_string (),
- "layer_map('+0/*;1-10/*;11-*/*';'+1-10/*')"
+ "layer_map('+*/*';'+1-10/*')"
);
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
@@ -524,7 +524,7 @@ TEST(8)
lm.mmap_expr ("5,15/*", n++);
EXPECT_EQ (lm.to_string (),
- "layer_map('+0/*;1-4/*;5/*;6-10/*;11-14/*;15/*;16-*/*';'+1-4/*;5/*;6-10/*';'+5/*;15/*')"
+ "layer_map('+*/*';'+1-10/*';'+5/*;15/*')"
);
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
@@ -535,8 +535,8 @@ TEST(8)
EXPECT_EQ (set2string (lm.logical (db::LDPair (10, 0))), "0,1");
// NOTE: the leading "+" indicates that the listed layers may go somewhere else, so we can't plainly map them
- EXPECT_EQ (lm.mapping_str (0), "+0/*;1-4/*;5/*;6-10/*;11-14/*;15/*;16-*/*");
- EXPECT_EQ (lm.mapping_str (1), "+1-4/*;5/*;6-10/*");
+ EXPECT_EQ (lm.mapping_str (0), "+*/*");
+ EXPECT_EQ (lm.mapping_str (1), "+1-10/*");
EXPECT_EQ (lm.mapping_str (2), "+5/*;15/*");
EXPECT_EQ (lm.mapping_str (3), "");
@@ -553,7 +553,7 @@ TEST(8)
// some
lm.mmap_expr ("1-10/0-20", n++);
EXPECT_EQ (lm.to_string (),
- "layer_map('+0/*;1-10/0-20,21-*;11-*/*';'+1-10/0-20')"
+ "layer_map('+*/*';'+1-10/0-20')"
);
EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ());
}
diff --git a/src/lay/lay/doc/about/layer_mapping.xml b/src/lay/lay/doc/about/layer_mapping.xml
index 81d6205db..2f3ea4c82 100644
--- a/src/lay/lay/doc/about/layer_mapping.xml
+++ b/src/lay/lay/doc/about/layer_mapping.xml
@@ -173,5 +173,33 @@
+
Multi-mapping and unmapping
+
+
+ Layer mapping table support an advanced feature which is to duplicate input layers to
+ a number of output layers (1:n) mapping.
+ The feature is enabled by prepending a "+" to the mapping statement. The following
+ statement will first select layer 5/0 and additionally copy it to layer 1000/0:
+
+
+ 5/0
++5/0: 1000/0
+
+
+
+ Unmapping removes the mapping for a specific layer or range. It is specified by prepending "-"
+ to the mapping expression. The following statement will map all datatypes of layer 5 to 0 except
+ for datatype 10 which is not considered.
+
+
+ 5/*: 5/0
+-5/10
+
+
+
+ Unmapping cancels the mappings specified previously, so the order of statements becomes important
+ when using unmapping and multi-mapping.
+
+
From dda2724d0c59dbffe7b08c87b2d6d1350cd5c63b Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 01:37:38 +0100
Subject: [PATCH 17/29] WIP: Documentation, mapping file option for buddy
scripts.
---
src/buddies/src/bd/bdReaderOptions.cc | 28 +++++++++++++++++++++++++++
src/buddies/src/bd/bdReaderOptions.h | 1 +
2 files changed, 29 insertions(+)
diff --git a/src/buddies/src/bd/bdReaderOptions.cc b/src/buddies/src/bd/bdReaderOptions.cc
index dec684c29..156e06048 100644
--- a/src/buddies/src/bd/bdReaderOptions.cc
+++ b/src/buddies/src/bd/bdReaderOptions.cc
@@ -24,6 +24,8 @@
#include "dbLoadLayoutOptions.h"
#include "tlCommandLineParser.h"
+#include "tlStream.h"
+
namespace bd
{
@@ -153,6 +155,13 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"layer is specified, all source layers addressed with the source specification are "
"combined into this target layer.\n"
"\n"
+ "To clone layers, add a mapping statement beginning with a '+' character. While other mapping statements "
+ "redefine mappings established before, mapping statement starting with '+' will clone the layer (1:m mapping).\n"
+ "\n"
+ "It's also possible to cancel mappings established before by using an 'unmap' statement. Such a statement "
+ "begins with a '-' and lists the layers whose mapping is to be removed. This is useful for creating "
+ "'mapping holes' in sequences.\n"
+ "\n"
"Examples:\n"
"\n"
"* 1/0 2/0 3/0-255:17/0\n"
@@ -160,6 +169,18 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"\n"
"* A:1/0 B:2/0\n"
" Maps named layer A to 1/0 and named layer B to 2/0"
+ "\n"
+ "* */*:*/* +10/*:1000/*"
+ " Includes all layers, but in addition copy all layers 10 to 1000 while keeping the datatype\n"
+ "\n"
+ "* */*:*/* -10/*"
+ " Includes all layers, but drops layer 10, all datatypes."
+ )
+ << tl::arg (group +
+ "--" + m_long_prefix + "layer-map-file=map", this, &GenericReaderOptions::set_layer_map_file, "Specifies the layer mapping for the input as a file",
+ "This option specifies the layer selection or mapping like + -" + m_prefix + ", but takes the mapping for the given file. "
+ "Each line in this file is read as one layer mapping expression. Empty lines or lines starting with a hash (#) character are "
+ "ignored."
)
;
}
@@ -610,6 +631,13 @@ void GenericReaderOptions::set_layer_map (const std::string &lm)
}
}
+void GenericReaderOptions::set_layer_map_file (const std::string &lm)
+{
+ tl::InputStream file (lm);
+ tl::TextInputStream text (file);
+ m_layer_map = db::LayerMap::from_string_file_format (text.read_all ());
+}
+
void GenericReaderOptions::set_read_named_layers (bool f)
{
m_keep_layer_names = f;
diff --git a/src/buddies/src/bd/bdReaderOptions.h b/src/buddies/src/bd/bdReaderOptions.h
index 7a0408ead..9caa9496c 100644
--- a/src/buddies/src/bd/bdReaderOptions.h
+++ b/src/buddies/src/bd/bdReaderOptions.h
@@ -134,6 +134,7 @@ private:
std::vector m_magic_lib_path;
void set_layer_map (const std::string &lm);
+ void set_layer_map_file (const std::string &lm);
void set_dbu (double dbu);
void set_read_named_layers (bool f);
From f86c13689b530b572e007bf957613f8075a1e465 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 13:21:33 +0100
Subject: [PATCH 18/29] WIP: some refactoring to simplify multi-mapping
implementation
---
src/db/db/dbCommonReader.cc | 80 +++++-
src/db/db/dbCommonReader.h | 264 +++++++++++-------
src/db/db/gsiDeclDbCommonStreamOptions.cc | 14 +-
.../db_plugin/contrib/dbGDS2TextReader.cc | 18 +-
.../gds2/db_plugin/contrib/dbGDS2TextReader.h | 35 +--
.../streamers/gds2/db_plugin/dbGDS2Reader.cc | 20 +-
.../streamers/gds2/db_plugin/dbGDS2Reader.h | 38 +--
.../gds2/db_plugin/dbGDS2ReaderBase.cc | 98 +------
.../gds2/db_plugin/dbGDS2ReaderBase.h | 31 +-
.../streamers/gds2/unit_tests/dbGDS2Reader.cc | 8 +-
.../oasis/db_plugin/dbOASISReader.cc | 128 ++-------
.../streamers/oasis/db_plugin/dbOASISReader.h | 42 +--
12 files changed, 308 insertions(+), 468 deletions(-)
diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc
index 2d4afc86d..f53db049b 100644
--- a/src/db/db/dbCommonReader.cc
+++ b/src/db/db/dbCommonReader.cc
@@ -35,7 +35,7 @@ namespace db
static const size_t null_id = std::numeric_limits::max ();
CommonReader::CommonReader ()
- : m_cc_resolution (AddToCell)
+ : m_cc_resolution (AddToCell), m_create_layers (false)
{
// .. nothing yet ..
}
@@ -275,6 +275,44 @@ CommonReader::merge_cell_without_instances (db::Layout &layout, db::cell_index_t
layout.delete_cell (src_cell.cell_index ());
}
+const db::LayerMap &
+CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
+{
+ init (options);
+
+ m_layer_map.prepare (layout);
+
+ layout.start_changes ();
+ try {
+ do_read (layout);
+ finish (layout);
+ layout.end_changes ();
+ } catch (...) {
+ layout.end_changes ();
+ throw;
+ }
+
+ return m_layer_map;
+}
+
+const db::LayerMap &
+CommonReader::read (db::Layout &layout)
+{
+ return read (layout, db::LoadLayoutOptions ());
+}
+
+void
+CommonReader::init (const LoadLayoutOptions &options)
+{
+ m_common_options = options.get_options ();
+ m_layer_map = m_common_options.layer_map;
+ m_cc_resolution = m_common_options.cell_conflict_resolution;
+ m_create_layers = m_common_options.create_other_layers;
+
+ m_layers_created.clear ();
+ m_layer_names.clear ();
+}
+
void
CommonReader::finish (db::Layout &layout)
{
@@ -384,6 +422,46 @@ CommonReader::finish (db::Layout &layout)
}
}
+std::pair
+CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
+{
+ std::pair ll = m_layer_map.first_logical (dl, layout);
+ if (ll.first) {
+
+ return ll;
+
+ } else if (! m_create_layers) {
+
+ return ll;
+
+ } else {
+
+ // and create the layer
+ db::LayerProperties lp;
+ lp.layer = dl.layer;
+ lp.datatype = dl.datatype;
+
+ // resolve OASIS name if possible
+ const tl::interval_map *names_dmap = m_layer_names.mapped (dl.layer);
+ if (names_dmap != 0) {
+ const std::string *name = names_dmap->mapped (dl.datatype);
+ if (name != 0) {
+ lp.name = *name;
+ }
+ }
+
+ unsigned int ll = layout.insert_layer (lp);
+ m_layer_map.map (dl, ll, lp);
+
+ m_layers_created.insert (ll);
+
+ return std::make_pair (true, ll);
+
+ }
+}
+
+
+
// ---------------------------------------------------------------
// Common format declaration
diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h
index f0ed56bcf..66b784972 100644
--- a/src/db/db/dbCommonReader.h
+++ b/src/db/db/dbCommonReader.h
@@ -31,6 +31,104 @@
namespace db
{
+/**
+ * @brief The CellConflictResolution enum
+ */
+enum CellConflictResolution
+{
+ AddToCell = 0,
+ OverwriteCell = 1,
+ SkipNewCell = 2,
+ RenameCell = 3
+};
+
+/**
+ * @brief Structure that holds the GDS2 and OASIS specific options for the reader
+ */
+class DB_PUBLIC CommonReaderOptions
+ : public FormatSpecificReaderOptions
+{
+public:
+ /**
+ * @brief The constructor
+ */
+ CommonReaderOptions ()
+ : create_other_layers (true),
+ enable_text_objects (true),
+ enable_properties (true),
+ cell_conflict_resolution (CellConflictResolution::AddToCell)
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief Specifies a layer mapping
+ *
+ * If a layer mapping is specified, only the given layers are read.
+ * Otherwise, all layers are read.
+ * Setting "create_other_layers" to true will make the reader
+ * create other layers for all layers not given in the layer map.
+ * Setting an empty layer map and create_other_layers to true effectively
+ * enables all layers for reading.
+ */
+ db::LayerMap layer_map;
+
+ /**
+ * @brief A flag indicating that a new layers shall be created
+ *
+ * If this flag is set to true, layers not listed in the layer map a created
+ * too.
+ */
+ bool create_other_layers;
+
+ /**
+ * @brief A flag indicating whether to read text objects
+ *
+ * If this flag is set to true, text objects are read. Otherwise they are ignored.
+ */
+ bool enable_text_objects;
+
+ /**
+ * @brief A flag indicating whether to read user properties
+ *
+ * If this flag is set to true, user properties are read. Otherwise they are ignored.
+ */
+ bool enable_properties;
+
+ /**
+ * @brief Specifies the cell merge behavior
+ *
+ * This enum controls how cells are read if a cell with the requested name already
+ * exists.
+ *
+ * AddToCell In this mode, instances or shapes are added to any existing cell
+ * OverwriteCell Overwrite existing cell. If the existing cell has children, those are removed unless used otherwise
+ * SkipNewCell Ignore the new cell and it's children
+ * RenameCell Rename the new cell
+ *
+ * If the existing opr the new cell is a ghost cell, AddToCell is applied always. In other words,
+ * ghost cells are always merged.
+ */
+ CellConflictResolution cell_conflict_resolution;
+
+ /**
+ * @brief Implementation of FormatSpecificReaderOptions
+ */
+ virtual FormatSpecificReaderOptions *clone () const
+ {
+ return new CommonReaderOptions (*this);
+ }
+
+ /**
+ * @brief Implementation of FormatSpecificReaderOptions
+ */
+ virtual const std::string &format_name () const
+ {
+ static const std::string n ("Common");
+ return n;
+ }
+};
+
/**
* @brief A common reader base for GDS2 and OASIS providing common services for both readers
*/
@@ -38,38 +136,13 @@ class DB_PUBLIC CommonReader
: public ReaderBase
{
public:
- /**
- * @brief The CellConflictResolution enum
- */
- enum CellConflictResolution
- {
- AddToCell = 0,
- OverwriteCell = 1,
- SkipNewCell = 2,
- RenameCell = 3
- };
+ typedef tl::interval_map > layer_name_map;
/**
* @brief Constructor
*/
CommonReader ();
- /**
- * @brief Sets the cell name conflict resolution mode
- */
- void set_cell_conflict_resolution (CellConflictResolution cc_resolution)
- {
- m_cc_resolution = cc_resolution;
- }
-
- /**
- * @brief Sets the cell name conflict resolution mode
- */
- CellConflictResolution cell_conflict_resolution () const
- {
- return m_cc_resolution;
- }
-
/**
* @brief Make a cell from a name
*/
@@ -132,9 +205,17 @@ public:
*/
void finish (db::Layout &layout);
+ // Reimplementation of the ReaderBase interace
+ virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
+ virtual const db::LayerMap &read (db::Layout &layout);
+
protected:
+ friend class CommonReaderLayerMapping;
+
virtual void common_reader_error (const std::string &msg) = 0;
virtual void common_reader_warn (const std::string &msg) = 0;
+ virtual void do_read (db::Layout &layout) = 0;
+ virtual void init (const LoadLayoutOptions &options);
/**
* @brief Merge (and delete) the src_cell into target_cell
@@ -146,98 +227,81 @@ protected:
*/
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
+ /**
+ * @brief Gets the common options
+ */
+ db::CommonReaderOptions &common_options ()
+ {
+ return m_common_options;
+ }
+
+ /**
+ * @brief Gets the layer map
+ */
+ db::LayerMap &layer_map ()
+ {
+ return m_layer_map;
+ }
+
+ /**
+ * @brief Gets the layer name map
+ */
+ layer_name_map &layer_names ()
+ {
+ return m_layer_names;
+ }
+
+ /**
+ * @brief Gets the list of layers which have been created
+ */
+ std::set &layers_created ()
+ {
+ return m_layers_created;
+ }
+
+ /**
+ * @brief Enters the a layer with a given layer/datatype
+ */
+ std::pair open_dl (db::Layout &layout, const LDPair &dl);
+
private:
std::map > m_id_map;
std::map > m_name_map;
std::map m_name_for_id;
CellConflictResolution m_cc_resolution;
+ bool m_create_layers;
+ db::CommonReaderOptions m_common_options;
+ db::LayerMap m_layer_map;
+ tl::interval_map > m_layer_names;
+ std::set m_layers_created;
};
/**
- * @brief Structure that holds the GDS2 and OASIS specific options for the reader
+ * @brief A utility class that maps the layers for the proxy cell recovery
*/
-class DB_PUBLIC CommonReaderOptions
- : public FormatSpecificReaderOptions
+class CommonReaderLayerMapping
+ : public db::ImportLayerMapping
{
public:
- /**
- * @brief The constructor
- */
- CommonReaderOptions ()
- : create_other_layers (true),
- enable_text_objects (true),
- enable_properties (true),
- cell_conflict_resolution (CommonReader::AddToCell)
+ CommonReaderLayerMapping (db::CommonReader *reader, db::Layout *layout)
+ : mp_reader (reader), mp_layout (layout)
{
// .. nothing yet ..
}
- /**
- * @brief Specifies a layer mapping
- *
- * If a layer mapping is specified, only the given layers are read.
- * Otherwise, all layers are read.
- * Setting "create_other_layers" to true will make the reader
- * create other layers for all layers not given in the layer map.
- * Setting an empty layer map and create_other_layers to true effectively
- * enables all layers for reading.
- */
- db::LayerMap layer_map;
-
- /**
- * @brief A flag indicating that a new layers shall be created
- *
- * If this flag is set to true, layers not listed in the layer map a created
- * too.
- */
- bool create_other_layers;
-
- /**
- * @brief A flag indicating whether to read text objects
- *
- * If this flag is set to true, text objects are read. Otherwise they are ignored.
- */
- bool enable_text_objects;
-
- /**
- * @brief A flag indicating whether to read user properties
- *
- * If this flag is set to true, user properties are read. Otherwise they are ignored.
- */
- bool enable_properties;
-
- /**
- * @brief Specifies the cell merge behavior
- *
- * This enum controls how cells are read if a cell with the requested name already
- * exists.
- *
- * AddToCell In this mode, instances or shapes are added to any existing cell
- * OverwriteCell Overwrite existing cell. If the existing cell has children, those are removed unless used otherwise
- * SkipNewCell Ignore the new cell and it's children
- * RenameCell Rename the new cell
- *
- * If the existing opr the new cell is a ghost cell, AddToCell is applied always. In other words,
- * ghost cells are always merged.
- */
- CommonReader::CellConflictResolution cell_conflict_resolution;
-
- /**
- * @brief Implementation of FormatSpecificReaderOptions
- */
- virtual FormatSpecificReaderOptions *clone () const
+ std::pair map_layer (const db::LayerProperties &lprops)
{
- return new CommonReaderOptions (*this);
+ // named layers that are imported from a library are ignored
+ if (lprops.is_named ()) {
+ return std::make_pair (false, 0);
+ } else {
+ return mp_reader->open_dl (*mp_layout, LDPair (lprops.layer, lprops.datatype));
+ }
}
- /**
- * @brief Implementation of FormatSpecificReaderOptions
- */
- virtual const std::string &format_name () const
- {
- static const std::string n ("Common");
- return n;
- }
+private:
+ db::CommonReader *mp_reader;
+ db::Layout *mp_layout;
};
}
diff --git a/src/db/db/gsiDeclDbCommonStreamOptions.cc b/src/db/db/gsiDeclDbCommonStreamOptions.cc
index 32b8ede8c..31245a050 100644
--- a/src/db/db/gsiDeclDbCommonStreamOptions.cc
+++ b/src/db/db/gsiDeclDbCommonStreamOptions.cc
@@ -85,12 +85,12 @@ static void set_properties_enabled (db::LoadLayoutOptions *options, bool l)
options->get_options ().enable_properties = l;
}
-static db::CommonReader::CellConflictResolution get_cell_conflict_resolution (const db::LoadLayoutOptions *options)
+static db::CellConflictResolution get_cell_conflict_resolution (const db::LoadLayoutOptions *options)
{
return options->get_options ().cell_conflict_resolution;
}
-static void set_cell_conflict_resolution (db::LoadLayoutOptions *options, db::CommonReader::CellConflictResolution cc)
+static void set_cell_conflict_resolution (db::LoadLayoutOptions *options, db::CellConflictResolution cc)
{
options->get_options ().cell_conflict_resolution = cc;
}
@@ -188,18 +188,18 @@ gsi::ClassExt common_reader_options (
);
-gsi::EnumIn decl_dbCommonReader_CellConflictResolution ("db", "CellConflictResolution",
- gsi::enum_const ("AddToCell", db::CommonReader::AddToCell,
+gsi::EnumIn decl_dbCommonReader_CellConflictResolution ("db", "CellConflictResolution",
+ gsi::enum_const ("AddToCell", db::AddToCell,
"@brief Add content to existing cell\n"
"This is the mode use in before version 0.27. Content of new cells is simply added to existing cells with the same name."
) +
- gsi::enum_const ("OverwriteCell", db::CommonReader::OverwriteCell,
+ gsi::enum_const ("OverwriteCell", db::OverwriteCell,
"@brief The old cell is overwritten entirely (including child cells which are not used otherwise)\n"
) +
- gsi::enum_const ("SkipNewCell", db::CommonReader::SkipNewCell,
+ gsi::enum_const ("SkipNewCell", db::SkipNewCell,
"@brief The new cell is skipped entirely (including child cells which are not used otherwise)\n"
) +
- gsi::enum_const ("RenameCell", db::CommonReader::RenameCell,
+ gsi::enum_const ("RenameCell", db::RenameCell,
"@brief The new cell will be renamed to become unique\n"
),
"@brief This enum specifies how cell conflicts are handled if a layout read into another layout and a cell name conflict arises. "
diff --git a/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.cc b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.cc
index ee363ed67..d25c92bfc 100644
--- a/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.cc
+++ b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.cc
@@ -51,23 +51,11 @@ GDS2ReaderText::~GDS2ReaderText()
// .. nothing yet ..
}
-const LayerMap &
-GDS2ReaderText::read (db::Layout &layout, const db::LoadLayoutOptions &options)
+void
+GDS2ReaderText::init (const db::LoadLayoutOptions &options)
{
+ GDS2ReaderBase::init (options);
storedRecId = 0;
-
- // HINT: reuse the standard GDS2 reader options for the text reader.
- // However, the allow_big_records and allow_multi_xy_records options are ignored.
- db::GDS2ReaderOptions gds2_options = options.get_options ();
- db::CommonReaderOptions common_options = options.get_options ();
-
- return basic_read (layout, common_options.layer_map, common_options.create_other_layers, common_options.enable_text_objects, common_options.enable_properties, false, gds2_options.box_mode, common_options.cell_conflict_resolution);
-}
-
-const LayerMap &
-GDS2ReaderText::read (db::Layout &layout)
-{
- return read (layout, db::LoadLayoutOptions ());
}
void
diff --git a/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.h b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.h
index 56de72863..2ec5b278a 100644
--- a/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.h
+++ b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.h
@@ -64,43 +64,14 @@ public:
*/
~GDS2ReaderText();
- /**
- * @brief The basic read method
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * It can be given a couple of options specified with the
- * LoadLayoutOptions object.
- * The returned map will contain all layers, the passed
- * ones and the newly created ones.
- *
- * @param layout The layout object to write to
- * @param options The generic reader options
- * @return The LayerMap object that tells where which layer was loaded
- */
- virtual const LayerMap &read (db::Layout &layout, const LoadLayoutOptions &options);
-
- /**
- * @brief The basic read method (without mapping)
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * This version will read all input layers and return a map
- * which tells which GDS2 layer has been read into which logical
- * layer.
- *
- * @param layout The layout object to write to
- * @return The LayerMap object
- */
- virtual const LayerMap &read (db::Layout &layout);
-
/**
* @brief Format
*/
const char *format () const { return "GDS2Text"; }
+protected:
+ virtual void init (const LoadLayoutOptions &options);
+
private:
tl::TextInputStream sStream;
std::string sExtractedValue;
diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.cc
index 772da9429..8838dafa9 100644
--- a/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.cc
+++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.cc
@@ -43,6 +43,7 @@ GDS2Reader::GDS2Reader (tl::InputStream &s)
m_recptr (0),
mp_rec_buf (0),
m_stored_rec (0),
+ m_allow_big_records (true),
m_progress (tl::to_string (tr ("Reading GDS2 file")), 10000)
{
m_progress.set_format (tl::to_string (tr ("%.0f MB")));
@@ -54,23 +55,16 @@ GDS2Reader::~GDS2Reader ()
// .. nothing yet ..
}
-const LayerMap &
-GDS2Reader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
+void
+GDS2Reader::init (const db::LoadLayoutOptions &options)
{
- m_options = options.get_options ();
- m_common_options = options.get_options ();
+ GDS2ReaderBase::init (options);
+
+ m_allow_big_records = options.get_options ().allow_big_records;
m_recnum = 0;
--m_recnum;
m_reclen = 0;
-
- return basic_read (layout, m_common_options.layer_map, m_common_options.create_other_layers, m_common_options.enable_text_objects, m_common_options.enable_properties, m_options.allow_multi_xy_records, m_options.box_mode, m_common_options.cell_conflict_resolution);
-}
-
-const LayerMap &
-GDS2Reader::read (db::Layout &layout)
-{
- return read (layout, db::LoadLayoutOptions ());
}
void
@@ -108,7 +102,7 @@ GDS2Reader::get_record ()
error (tl::to_string (tr ("Invalid record length (less than 4)")));
}
if (m_reclen >= 0x8000) {
- if (m_options.allow_big_records) {
+ if (m_allow_big_records) {
warn (tl::to_string (tr ("Record length larger than 0x8000 encountered: interpreting as unsigned")));
} else {
error (tl::to_string (tr ("Record length larger than 0x8000 encountered (reader is configured not to allow such records)")));
diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.h
index 2b51144dd..21d1b5b05 100644
--- a/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.h
+++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.h
@@ -72,43 +72,14 @@ public:
*/
~GDS2Reader ();
- /**
- * @brief The basic read method
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * It can be given a couple of options specified with the
- * LoadLayoutOptions object.
- * The returned map will contain all layers, the passed
- * ones and the newly created ones.
- *
- * @param layout The layout object to write to
- * @param options The generic reader options
- * @return The LayerMap object that tells where which layer was loaded
- */
- virtual const LayerMap &read (db::Layout &layout, const LoadLayoutOptions &options);
-
- /**
- * @brief The basic read method (without mapping)
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * This version will read all input layers and return a map
- * which tells which GDS2 layer has been read into which logical
- * layer.
- *
- * @param layout The layout object to write to
- * @return The LayerMap object
- */
- virtual const LayerMap &read (db::Layout &layout);
-
/**
* @brief Format
*/
virtual const char *format () const { return "GDS2"; }
+protected:
+ virtual void init (const LoadLayoutOptions &options);
+
private:
tl::InputStream &m_stream;
size_t m_recnum;
@@ -117,8 +88,7 @@ private:
unsigned char *mp_rec_buf;
tl::string m_string_buf;
short m_stored_rec;
- db::GDS2ReaderOptions m_options;
- db::CommonReaderOptions m_common_options;
+ bool m_allow_big_records;
tl::AbsoluteProgress m_progress;
virtual void error (const std::string &txt);
diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc
index 7111089d9..d55020fa5 100644
--- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc
+++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc
@@ -22,6 +22,7 @@
#include "dbGDS2ReaderBase.h"
+#include "dbGDS2Format.h"
#include "dbGDS2.h"
#include "dbArray.h"
@@ -34,42 +35,12 @@ namespace db
// ---------------------------------------------------------------
-/**
- * @brief A utility class that maps the layers for the proxy cell recovery
- */
-class GDS2ReaderLayerMapping
- : public db::ImportLayerMapping
-{
-public:
- GDS2ReaderLayerMapping (db::GDS2ReaderBase *reader, db::Layout *layout, bool create)
- : mp_reader (reader), mp_layout (layout), m_create (create)
- {
- // .. nothing yet ..
- }
-
- std::pair map_layer (const db::LayerProperties &lprops)
- {
- // named layers that are imported from a library are ignored
- if (lprops.is_named ()) {
- return std::make_pair (false, 0);
- } else {
- return mp_reader->open_dl (*mp_layout, LDPair (lprops.layer, lprops.datatype), m_create);
- }
- }
-
-private:
- db::GDS2ReaderBase *mp_reader;
- db::Layout *mp_layout;
- bool m_create;
-};
-
// ---------------------------------------------------------------
// GDS2ReaderBase
GDS2ReaderBase::GDS2ReaderBase ()
: m_dbu (0.001),
m_dbuu (1.0),
- m_create_layers (true),
m_read_texts (true),
m_read_properties (true),
m_allow_multi_xy_records (false),
@@ -83,31 +54,18 @@ GDS2ReaderBase::~GDS2ReaderBase ()
// .. nothing yet ..
}
-const LayerMap &
-GDS2ReaderBase::basic_read (db::Layout &layout, const LayerMap &layer_map, bool create_other_layers, bool enable_text_objects, bool enable_properties, bool allow_multi_xy_records, unsigned int box_mode, db::CommonReader::CellConflictResolution cc_resolution)
+void
+GDS2ReaderBase::init (const db::LoadLayoutOptions &options)
{
- m_layer_map = layer_map;
- m_layer_map.prepare (layout);
- m_read_texts = enable_text_objects;
- m_read_properties = enable_properties;
+ CommonReader::init (options);
- m_allow_multi_xy_records = allow_multi_xy_records;
- m_box_mode = box_mode;
- m_create_layers = create_other_layers;
+ db::GDS2ReaderOptions gds2_options = options.get_options ();
- set_cell_conflict_resolution (cc_resolution);
+ m_read_texts = common_options ().enable_text_objects;
+ m_read_properties = common_options ().enable_properties;
- layout.start_changes ();
- try {
- do_read (layout);
- finish (layout);
- layout.end_changes ();
- } catch (...) {
- layout.end_changes ();
- throw;
- }
-
- return m_layer_map;
+ m_allow_multi_xy_records = gds2_options.allow_multi_xy_records;
+ m_box_mode = gds2_options.box_mode;
}
void
@@ -181,34 +139,6 @@ 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.first_logical (dl, layout);
- if (ll.first) {
-
- return ll;
-
- } else if (! create) {
-
- // layer not mapped and no layer create is requested
- return ll;
-
- } else {
-
- // and create the layer
- db::LayerProperties lp;
- lp.layer = dl.layer;
- lp.datatype = dl.datatype;
-
- unsigned int ll = layout.insert_layer (lp);
- m_layer_map.map (dl, ll, lp);
-
- return std::make_pair (true, ll);
-
- }
-}
-
inline db::Point
pt_conv (const GDS2XY &p)
{
@@ -362,7 +292,7 @@ GDS2ReaderBase::do_read (db::Layout &layout)
std::map >::const_iterator ctx = m_context_info.find (m_cellname);
if (ctx != m_context_info.end ()) {
- GDS2ReaderLayerMapping layer_mapping (this, &layout, m_create_layers);
+ CommonReaderLayerMapping layer_mapping (this, &layout);
if (layout.recover_proxy_as (cell_index, ctx->second.begin (), ctx->second.end (), &layer_mapping)) {
// ignore everything in that cell since it is created by the import:
cell = 0;
@@ -553,7 +483,7 @@ GDS2ReaderBase::read_boundary (db::Layout &layout, db::Cell &cell, bool from_box
unsigned int xy_length = 0;
GDS2XY *xy_data = get_xy_data (xy_length);
- std::pair ll = open_dl (layout, ld, m_create_layers);
+ std::pair ll = open_dl (layout, ld);
if (ll.first) {
// create a box object if possible
@@ -734,7 +664,7 @@ GDS2ReaderBase::read_path (db::Layout &layout, db::Cell &cell)
unsigned int xy_length = 0;
GDS2XY *xy_data = get_xy_data (xy_length);
- std::pair ll = open_dl (layout, ld, m_create_layers);
+ std::pair ll = open_dl (layout, ld);
if (ll.first) {
// this will copy the path:
@@ -825,7 +755,7 @@ GDS2ReaderBase::read_text (db::Layout &layout, db::Cell &cell)
std::pair ll (false, 0);
if (m_read_texts) {
- ll = open_dl (layout, ld, m_create_layers);
+ ll = open_dl (layout, ld);
}
rec_id = get_record ();
@@ -947,7 +877,7 @@ GDS2ReaderBase::read_box (db::Layout &layout, db::Cell &cell)
}
ld.datatype = get_ushort ();
- std::pair ll = open_dl (layout, ld, m_create_layers);
+ std::pair ll = open_dl (layout, ld);
if (get_record () != sXY) {
error (tl::to_string (tr ("XY record expected")));
diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.h
index a094da9fb..d31c0c537 100644
--- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.h
+++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.h
@@ -69,42 +69,20 @@ public:
const std::string &libname () const { return m_libname; }
protected:
- /**
- * @brief The basic read method
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * It can be given a couple of options specified with the
- * LoadLayoutOptions object.
- * The returned map will contain all layers, the passed
- * ones and the newly created ones.
- *
- * @param layout The layout object to write to
- * @param layer_map The layer mapping on input
- * @param create_other_layer A flag indicating whether to read all other layers
- * @param enable_text_objects A flag indicating whether to read text objects
- * @param enable_properties A flag indicating whether to read user properties
- * @param allow_multi_xy_records If true, tries to check for multiple XY records for BOUNDARY elements
- * @param box_mode How to treat BOX records (0: ignore, 1: as rectangles, 2: as boundaries, 3: error)
- * @param cc_resolution The cell name conflict resolution mode
- * @return The LayerMap object that tells where which layer was loaded
- */
- const LayerMap &basic_read (db::Layout &layout, const LayerMap &layer_map, bool create_other_layers, bool enable_text_objects, bool enable_properties, bool allow_multi_xy_records, unsigned int box_mode, db::CommonReader::CellConflictResolution cc_resolution);
-
/**
* @brief Accessor method to the current cellname
*/
const std::string &cellname () const { return m_cellname; }
+ virtual void do_read (db::Layout &layout);
+ virtual void init (const LoadLayoutOptions &options);
+
private:
friend class GDS2ReaderLayerMapping;
- LayerMap m_layer_map;
std::string m_cellname;
std::string m_libname;
double m_dbu, m_dbuu;
- bool m_create_layers;
bool m_read_texts;
bool m_read_properties;
bool m_allow_multi_xy_records;
@@ -119,9 +97,6 @@ private:
void read_box (db::Layout &layout, db::Cell &cell);
void read_ref (db::Layout &layout, db::Cell &cell, bool array, tl::vector &instances, tl::vector &insts_wp);
- void do_read (db::Layout &layout);
-
- std::pair open_dl (db::Layout &layout, const LDPair &dl, bool create);
std::pair finish_element (db::PropertiesRepository &rep);
void finish_element ();
diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
index 7361c67a2..dc53a8db7 100644
--- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
+++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
@@ -443,7 +443,7 @@ TEST(4_CollectModeRename)
db::Layout layout (&m);
db::LoadLayoutOptions options;
- options.get_options ().cell_conflict_resolution = db::CommonReader::RenameCell;
+ options.get_options ().cell_conflict_resolution = db::RenameCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
@@ -467,7 +467,7 @@ TEST(4_CollectModeOverwrite)
db::Layout layout (&m);
db::LoadLayoutOptions options;
- options.get_options ().cell_conflict_resolution = db::CommonReader::OverwriteCell;
+ options.get_options ().cell_conflict_resolution = db::OverwriteCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
@@ -491,7 +491,7 @@ TEST(4_CollectModeSkip)
db::Layout layout (&m);
db::LoadLayoutOptions options;
- options.get_options ().cell_conflict_resolution = db::CommonReader::SkipNewCell;
+ options.get_options ().cell_conflict_resolution = db::SkipNewCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
@@ -515,7 +515,7 @@ TEST(4_CollectModeAdd)
db::Layout layout (&m);
db::LoadLayoutOptions options;
- options.get_options ().cell_conflict_resolution = db::CommonReader::AddToCell;
+ options.get_options ().cell_conflict_resolution = db::AddToCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
index 131fb3e9a..ce6f1a3f1 100644
--- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
+++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
@@ -38,35 +38,6 @@ namespace db
// ---------------------------------------------------------------
-/**
- * @brief A utility class that maps the layers for the proxy cell recovery
- */
-class OASISReaderLayerMapping
- : public db::ImportLayerMapping
-{
-public:
- OASISReaderLayerMapping (db::OASISReader *reader, db::Layout *layout, bool create)
- : mp_reader (reader), mp_layout (layout), m_create (create)
- {
- // .. nothing yet ..
- }
-
- std::pair map_layer (const db::LayerProperties &lprops)
- {
- // named layers that are imported from a library are ignored
- if (lprops.is_named ()) {
- return std::make_pair (false, 0);
- } else {
- return mp_reader->open_dl (*mp_layout, LDPair (lprops.layer, lprops.datatype), m_create);
- }
- }
-
-private:
- db::OASISReader *mp_reader;
- db::Layout *mp_layout;
- bool m_create;
-};
-
// ---------------------------------------------------------------
// OASISReader
@@ -101,7 +72,6 @@ OASISReader::OASISReader (tl::InputStream &s)
mm_last_property_name (this, "last-property-name"),
mm_last_property_is_sprop (this, "last-property-is-stdprop"),
mm_last_value_list(this, "last-value-list"),
- m_create_layers (false),
m_read_texts (true),
m_read_properties (true),
m_read_all_properties (false),
@@ -129,40 +99,17 @@ OASISReader::~OASISReader ()
// .. nothing yet ..
}
-const LayerMap &
-OASISReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
+void
+OASISReader::init (const db::LoadLayoutOptions &options)
{
- db::OASISReaderOptions oasis_options = options.get_options ();
- db::CommonReaderOptions common_options = options.get_options ();
+ CommonReader::init (options);
- m_layer_map = common_options.layer_map;
- m_layer_map.prepare (layout);
- m_layers_created.clear ();
- m_read_texts = common_options.enable_text_objects;
- m_read_properties = common_options.enable_properties;
- m_create_layers = common_options.create_other_layers;
+ m_read_texts = common_options ().enable_text_objects;
+ m_read_properties = common_options ().enable_properties;
+
+ db::OASISReaderOptions oasis_options = options.get_options ();
m_read_all_properties = oasis_options.read_all_properties;
m_expect_strict_mode = oasis_options.expect_strict_mode;
-
- set_cell_conflict_resolution (common_options.cell_conflict_resolution);
-
- layout.start_changes ();
- try {
- do_read (layout);
- finish (layout);
- layout.end_changes ();
- } catch (...) {
- layout.end_changes ();
- throw;
- }
-
- return m_layer_map;
-}
-
-const LayerMap &
-OASISReader::read (db::Layout &layout)
-{
- return read (layout, db::LoadLayoutOptions ());
}
inline long long
@@ -554,44 +501,6 @@ 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.first_logical (dl, layout);
- if (ll.first) {
-
- return ll;
-
- } else if (! create) {
-
- return ll;
-
- } else {
-
- // and create the layer
- db::LayerProperties lp;
- lp.layer = dl.layer;
- lp.datatype = dl.datatype;
-
- // resolve OASIS name if possible
- const tl::interval_map *names_dmap = m_layernames.mapped (dl.layer);
- if (names_dmap != 0) {
- const std::string *name = names_dmap->mapped (dl.datatype);
- if (name != 0) {
- lp.name = *name;
- }
- }
-
- unsigned int ll = layout.insert_layer (lp);
- m_layer_map.map (dl, ll, lp);
-
- m_layers_created.insert (ll);
-
- return std::make_pair (true, ll);
-
- }
-}
-
/**
* @brief A helper class to join two datatype layer name map members
*/
@@ -765,7 +674,6 @@ OASISReader::do_read (db::Layout &layout)
m_textstrings.clear ();
m_propstrings.clear ();
m_propnames.clear ();
- m_layernames.clear ();
m_instances.clear ();
m_instances_with_props.clear ();
@@ -1077,10 +985,10 @@ OASISReader::do_read (db::Layout &layout)
LNameJoinOp1 op1;
dt_map.add (dt1, dt2 + 1, name, op1);
LNameJoinOp2 op2;
- m_layernames.add (l1, l2 + 1, dt_map, op2);
+ layer_names ().add (l1, l2 + 1, dt_map, op2);
// rename layers created before if required
- for (std::set::const_iterator i = m_layers_created.begin (); i != m_layers_created.end (); ++i) {
+ for (std::set::const_iterator i = layers_created ().begin (); i != layers_created ().end (); ++i) {
const db::LayerProperties &lp = layout.get_properties (*i);
if (lp.layer >= l1 && lp.layer <= l2 && lp.datatype >= dt1 && lp.datatype <= dt2 && lp.name != name) {
// need to rename: add a new madding to m_layer_map and adjust the layout's layer properties
@@ -1088,7 +996,7 @@ OASISReader::do_read (db::Layout &layout)
LNameJoinOp1 nj;
nj (lpp.name, name);
layout.set_properties (*i, lpp);
- m_layer_map.map (LDPair (lp.layer, lp.datatype), *i, lpp);
+ layer_map ().map (LDPair (lp.layer, lp.datatype), *i, lpp);
}
}
@@ -2038,7 +1946,7 @@ OASISReader::do_read_text (bool xy_absolute,
std::pair ll (false, 0);
if (m_read_texts) {
- ll = open_dl (layout, LDPair (mm_textlayer.get (), mm_texttype.get ()), m_create_layers);
+ ll = open_dl (layout, LDPair (mm_textlayer.get (), mm_texttype.get ()));
}
if ((m & 0x4) && read_repetition ()) {
@@ -2180,7 +2088,7 @@ OASISReader::do_read_rectangle (bool xy_absolute,
db::Box box (db::Point (mm_geometry_x.get (), mm_geometry_y.get ()),
db::Point (mm_geometry_x.get () + mm_geometry_w.get (), mm_geometry_y.get () + mm_geometry_h.get ()));
- std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
+ std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
if ((m & 0x4) && read_repetition ()) {
@@ -2294,7 +2202,7 @@ OASISReader::do_read_polygon (bool xy_absolute, db::cell_index_type cell_index,
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
- std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
+ std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
if ((m & 0x4) && read_repetition ()) {
@@ -2461,7 +2369,7 @@ OASISReader::do_read_path (bool xy_absolute, db::cell_index_type cell_index, db:
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
- std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
+ std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
if ((m & 0x4) && read_repetition ()) {
@@ -2620,7 +2528,7 @@ OASISReader::do_read_trapezoid (unsigned char r, bool xy_absolute,db::cell_index
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
- std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
+ std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
db::Point pts [4];
@@ -2775,7 +2683,7 @@ OASISReader::do_read_ctrapezoid (bool xy_absolute,db::cell_index_type cell_index
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
- std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
+ std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
db::Point pts [4];
@@ -3126,7 +3034,7 @@ OASISReader::do_read_circle (bool xy_absolute, db::cell_index_type cell_index, d
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
- std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
+ std::pair ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
// ignore this circle if the radius is zero
if (mm_circle_radius.get () <= 0) {
@@ -3444,7 +3352,7 @@ OASISReader::do_read_cell (db::cell_index_type cell_index, db::Layout &layout)
// Restore proxy cell (link to PCell or Library)
if (has_context) {
- OASISReaderLayerMapping layer_mapping (this, &layout, m_create_layers);
+ CommonReaderLayerMapping layer_mapping (this, &layout);
layout.recover_proxy_as (cell_index, context_strings.begin (), context_strings.end (), &layer_mapping);
}
diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h
index a8a56e173..89b18d5fd 100644
--- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h
+++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.h
@@ -81,39 +81,6 @@ public:
*/
~OASISReader ();
- /**
- * @brief The basic read method
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * A set of options can be specified with the LoadLayoutOptions
- * object.
- * The returned map will contain all layers, the passed
- * ones and the newly created ones.
- *
- * @param layout The layout object to write to
- * @param map The LayerMap object
- * @param create true, if new layers should be created
- * @return The LayerMap object that tells where which layer was loaded
- */
- virtual const LayerMap &read (db::Layout &layout, const LoadLayoutOptions &options);
-
- /**
- * @brief The basic read method (without mapping)
- *
- * This method will read the stream data and translate this to
- * insert calls into the layout object. This will not do much
- * on the layout object beside inserting the objects.
- * This version will read all input layers and return a map
- * which tells which OASIS layer has been read into which logical
- * layer.
- *
- * @param layout The layout object to write to
- * @return The LayerMap object
- */
- virtual const LayerMap &read (db::Layout &layout);
-
/**
* @brief Format
*/
@@ -136,6 +103,8 @@ protected:
virtual void common_reader_error (const std::string &msg) { error (msg); }
virtual void common_reader_warn (const std::string &msg) { warn (msg); }
+ virtual void init (const LoadLayoutOptions &options);
+ virtual void do_read (db::Layout &layout);
private:
friend class OASISReaderLayerMapping;
@@ -153,8 +122,6 @@ private:
};
tl::InputStream &m_stream;
- LayerMap m_layer_map;
- std::set m_layers_created;
tl::AbsoluteProgress m_progress;
std::string m_cellname;
double m_dbu;
@@ -204,12 +171,10 @@ private:
std::map m_text_forward_references;
std::map m_propstrings;
std::map m_propnames;
- tl::interval_map > m_layernames;
tl::vector m_instances;
tl::vector m_instances_with_props;
- bool m_create_layers;
bool m_read_texts;
bool m_read_properties;
bool m_read_all_properties;
@@ -219,7 +184,6 @@ private:
db::property_names_id_type m_s_gds_property_name_id;
db::property_names_id_type m_klayout_context_property_name_id;
- void do_read (db::Layout &layout);
void do_read_cell (db::cell_index_type cell_index, db::Layout &layout);
void do_read_placement (unsigned char r,
@@ -310,8 +274,6 @@ private:
db::Coord get_coord (long grid = 1);
db::Coord get_ucoord (unsigned long grid = 1);
distance_type get_ucoord_as_distance (unsigned long grid = 1);
-
- std::pair open_dl (db::Layout &layout, const LDPair &dl, bool create);
};
}
From a1eb8c121b6b9ecfc643161cd194f3ab8cd577b3 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 15:36:03 +0100
Subject: [PATCH 19/29] WIP: implementation for GDS2 and OASIS, added tests.
---
src/db/db/dbCommonReader.cc | 166 ++++++++++++++++--
src/db/db/dbCommonReader.h | 25 +--
.../streamers/gds2/unit_tests/dbGDS2Reader.cc | 49 +++++-
.../oasis/db_plugin/dbOASISReader.cc | 20 +--
testdata/gds/alm_au2.gds | Bin 0 -> 11842 bytes
5 files changed, 201 insertions(+), 59 deletions(-)
create mode 100644 testdata/gds/alm_au2.gds
diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc
index f53db049b..59d59f16f 100644
--- a/src/db/db/dbCommonReader.cc
+++ b/src/db/db/dbCommonReader.cc
@@ -32,6 +32,34 @@ namespace db
// ---------------------------------------------------------------
// Common reader implementation
+DB_PUBLIC void
+join_layer_names (std::string &s, const std::string &n)
+{
+ if (s == n) {
+ return;
+ }
+
+ if (! s.empty ()) {
+
+ size_t i = s.find (n);
+ if (i != std::string::npos && (i == 0 || s.c_str ()[i - 1] == ';')) {
+ char after = s.c_str ()[i + n.size ()];
+ if (after == 0 || after == ';') {
+ // n is already contained in s
+ return;
+ }
+ }
+
+ s += ";";
+
+ }
+
+ s += n;
+}
+
+// ---------------------------------------------------------------
+// Common reader implementation
+
static const size_t null_id = std::numeric_limits::max ();
CommonReader::CommonReader ()
@@ -280,7 +308,7 @@ CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
init (options);
- m_layer_map.prepare (layout);
+ m_common_options.layer_map.prepare (layout);
layout.start_changes ();
try {
@@ -292,7 +320,7 @@ CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
throw;
}
- return m_layer_map;
+ return m_layer_map_out;
}
const db::LayerMap &
@@ -305,12 +333,23 @@ void
CommonReader::init (const LoadLayoutOptions &options)
{
m_common_options = options.get_options ();
- m_layer_map = m_common_options.layer_map;
m_cc_resolution = m_common_options.cell_conflict_resolution;
m_create_layers = m_common_options.create_other_layers;
+ m_layer_map_out.clear ();
+ m_multi_mapping_placeholders.clear ();
+ m_layer_cache.clear ();
m_layers_created.clear ();
m_layer_names.clear ();
+
+ // create a pseudo-multimapping for single targets
+ for (db::LayerMap::const_iterator_layers li = m_common_options.layer_map.begin (); li != m_common_options.layer_map.end (); ++li) {
+ for (db::LayerMap::const_iterator_datatypes di = li->second.begin (); di != li->second.end (); ++di) {
+ if (di->second.size () == 1) {
+ m_multi_mapping_placeholders.insert (std::make_pair (di->second, *di->second.begin ()));
+ }
+ }
+ }
}
void
@@ -420,21 +459,77 @@ CommonReader::finish (db::Layout &layout)
}
}
+
+ // resolve layer multi-mapping
+
+ for (std::map, unsigned int>::const_iterator i = m_multi_mapping_placeholders.begin (); i != m_multi_mapping_placeholders.end (); ++i) {
+
+ if (i->first.size () > 1) {
+
+ bool discard_layer = i->first.find (i->second) == i->first.end ();
+
+ for (std::set::const_iterator l = i->first.begin (); l != i->first.end (); ++l) {
+
+ // last one? this one will get a "move"
+ std::set::const_iterator ll = l;
+ if (discard_layer && ++ll == i->first.end ()) {
+ layout.move_layer (i->second, *l);
+ layout.delete_layer (i->second);
+ } else {
+ layout.copy_layer (i->second, *l);
+ }
+
+ }
+
+ }
+
+ }
+
+ // rename layers created before if required
+
+ for (std::set::const_iterator i = m_layers_created.begin (); i != m_layers_created.end (); ++i) {
+
+ const db::LayerProperties &lp = layout.get_properties (*i);
+
+ const tl::interval_map *dtmap = layer_names ().mapped (lp.layer);
+ const std::string *name = 0;
+ if (dtmap) {
+ name = dtmap->mapped (lp.datatype);
+ }
+
+ if (name) {
+ // need to rename: add a new madding to m_layer_map_out and adjust the layout's layer properties
+ db::LayerProperties lpp = lp;
+ join_layer_names (lpp.name, *name);
+ layout.set_properties (*i, lpp);
+ m_layer_map_out.map (LDPair (lp.layer, lp.datatype), *i, lpp);
+ }
+
+ }
}
std::pair
CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
{
- std::pair ll = m_layer_map.first_logical (dl, layout);
- if (ll.first) {
-
- return ll;
-
- } else if (! m_create_layers) {
-
- return ll;
-
+ std::map >::const_iterator lc = m_layer_cache.find (dl);
+ if (lc != m_layer_cache.end ()) {
+ return lc->second;
} else {
+ std::pair res = open_dl_uncached (layout, dl);
+ m_layer_cache.insert (std::make_pair (dl, res));
+ return res;
+ }
+}
+
+std::pair
+CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl)
+{
+ const std::set &li = common_options ().layer_map.logical (dl, layout);
+ if (li.empty ()) {
+
+ if (! m_create_layers) {
+ return std::make_pair (false, (unsigned int) 0);
+ }
// and create the layer
db::LayerProperties lp;
@@ -450,18 +545,53 @@ CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
}
}
- unsigned int ll = layout.insert_layer (lp);
- m_layer_map.map (dl, ll, lp);
+ unsigned int nl = layout.insert_layer (lp);
+ m_layer_map_out.map (dl, nl, lp);
- m_layers_created.insert (ll);
+ m_layers_created.insert (nl);
- return std::make_pair (true, ll);
+ return std::make_pair (true, nl);
+
+ } else if (li.size () == 1) {
+
+ m_layer_map_out.map (dl, *li.begin (), layout.get_properties (*li.begin ()));
+
+ return std::make_pair (true, *li.begin ());
+
+ } else {
+
+ std::map, unsigned int>::iterator mmp = m_multi_mapping_placeholders.find (li);
+ if (mmp == m_multi_mapping_placeholders.end ()) {
+
+ // multi-mapping: create a placeholder layer if required
+
+ for (std::set::const_iterator i = li.begin (); i != li.end (); ++i) {
+ m_layer_map_out.mmap (dl, *i, layout.get_properties (*i));
+ }
+
+ for (std::set::const_iterator i = li.begin (); i != li.end (); ++i) {
+ std::set sl;
+ sl.insert (*i);
+ if (m_multi_mapping_placeholders.find (sl) == m_multi_mapping_placeholders.end ()) {
+ // a layer not used in a single-target context can be used as a placeholder layer (but only once)
+ m_multi_mapping_placeholders.insert (std::make_pair (sl, *i));
+ mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, *i)).first;
+ break;
+ }
+ }
+
+ if (mmp == m_multi_mapping_placeholders.end ()) {
+ // create a placeholder layer for later
+ mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, layout.insert_layer ())).first;
+ }
+
+ }
+
+ return std::make_pair (true, mmp->second);
}
}
-
-
// ---------------------------------------------------------------
// Common format declaration
diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h
index 66b784972..cf53f1895 100644
--- a/src/db/db/dbCommonReader.h
+++ b/src/db/db/dbCommonReader.h
@@ -31,6 +31,9 @@
namespace db
{
+DB_PUBLIC void
+join_layer_names (std::string &s, const std::string &n);
+
/**
* @brief The CellConflictResolution enum
*/
@@ -235,14 +238,6 @@ protected:
return m_common_options;
}
- /**
- * @brief Gets the layer map
- */
- db::LayerMap &layer_map ()
- {
- return m_layer_map;
- }
-
/**
* @brief Gets the layer name map
*/
@@ -251,14 +246,6 @@ protected:
return m_layer_names;
}
- /**
- * @brief Gets the list of layers which have been created
- */
- std::set &layers_created ()
- {
- return m_layers_created;
- }
-
/**
* @brief Enters the a layer with a given layer/datatype
*/
@@ -271,9 +258,13 @@ private:
CellConflictResolution m_cc_resolution;
bool m_create_layers;
db::CommonReaderOptions m_common_options;
- db::LayerMap m_layer_map;
+ db::LayerMap m_layer_map_out;
tl::interval_map > m_layer_names;
+ std::map > m_layer_cache;
+ std::map, unsigned int> m_multi_mapping_placeholders;
std::set m_layers_created;
+
+ std::pair open_dl_uncached (db::Layout &layout, const LDPair &dl);
};
/**
diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
index dc53a8db7..d045b10d3 100644
--- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
+++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
@@ -418,7 +418,7 @@ TEST(3_AdvancedMapping)
EXPECT_EQ (lm_read.to_string_file_format (),
"1/10 : 1/0\n"
- "2/0-9,21-*\n"
+ "2/0-1 : 2/0\n"
"1/0 : 1/0\n"
"1/1 : 1/1\n"
"1/20 : 1/1020\n"
@@ -427,16 +427,55 @@ TEST(3_AdvancedMapping)
"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);
}
+TEST(3_MultiMapping)
+{
+ db::Manager m (false);
+ db::Layout layout (&m);
+
+ db::LoadLayoutOptions options;
+ db::LayerMap lm, lm_read;
+
+ unsigned int n = 0;
+ lm.map_expr ("*/*: */*", n++);
+ lm.unmap_expr ("1-2/10");
+ lm.mmap_expr ("1-2/10: *+100/*", n++);
+ lm.mmap_expr ("1/10;2/10: 12/1010", n++);
+ lm.mmap_expr ("1/0-1: */*+1000", 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-2/10 : 12/1010\n"
+ "+1/0 : 1/1000\n"
+ "+1/0 : 1/0\n"
+ "+1/1 : 1/1001\n"
+ "+1/1 : 1/1\n"
+ "+1/10 : 101/10\n"
+ "1/20 : 1/20\n"
+ "1/21 : 1/21\n"
+ "2/0 : 2/0\n"
+ "2/1 : 2/1\n"
+ "+2/10 : 102/10\n"
+ "2/11 : 2/11\n"
+ "42/42 : 42/42\n"
+ "100/0 : 100/0\n"
+ );
+
+ std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au2.gds");
+ db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
+}
+
TEST(4_CollectModeRename)
{
db::Manager m (false);
diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
index ce6f1a3f1..5042790a8 100644
--- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
+++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc
@@ -508,12 +508,7 @@ struct LNameJoinOp1
{
void operator() (std::string &a, const std::string &b)
{
- if (a != b) {
- if (! a.empty ()) {
- a += ";";
- }
- a += b;
- }
+ join_layer_names (a, b);
}
};
@@ -987,19 +982,6 @@ OASISReader::do_read (db::Layout &layout)
LNameJoinOp2 op2;
layer_names ().add (l1, l2 + 1, dt_map, op2);
- // rename layers created before if required
- for (std::set::const_iterator i = layers_created ().begin (); i != layers_created ().end (); ++i) {
- const db::LayerProperties &lp = layout.get_properties (*i);
- if (lp.layer >= l1 && lp.layer <= l2 && lp.datatype >= dt1 && lp.datatype <= dt2 && lp.name != name) {
- // need to rename: add a new madding to m_layer_map and adjust the layout's layer properties
- db::LayerProperties lpp = lp;
- LNameJoinOp1 nj;
- nj (lpp.name, name);
- layout.set_properties (*i, lpp);
- layer_map ().map (LDPair (lp.layer, lp.datatype), *i, lpp);
- }
- }
-
reset_modal_variables ();
// ignore properties attached to this name item
diff --git a/testdata/gds/alm_au2.gds b/testdata/gds/alm_au2.gds
new file mode 100644
index 0000000000000000000000000000000000000000..4492ec4d999fe06e34e1a83c544f52a0f82083d4
GIT binary patch
literal 11842
zcmeI2L1>*-7RPU1UcQ&UrZH)g+StUlQ)8P_P)bo}7LpMuGhRe7kX-~Q#9Y_PcpVMHgn)~HFDUJ0H-2L;H
z@4WBBKYa1idoSE}{_TfPr^$hJ;;QQO0}rOu9!#m))l&9qxYhqUHlJSK2nEMrSU;f=!Q|dcjllZ=6&jTaB*dAS7#~gL2@8$;w&!p6UMeTj%
z>^`iZIpxo!p4JDRACf=EH|4i}w*TaQkopFmsY$+pQ{K<^zrCOM(N81yvDejQB)@vwW;?c^VP)AJ8r&GvKkea3@$#-}4Y@q9Ka&OVFy
z@tM4l2ZkSY<~o|{{2+9({~@36$zO}}DNVkwd3`in)4TZk)Qb|4!s2FH~NC;i*ds*X!qsMIH0c}@#v~B@;BE}^hF)$ia5x8
zFyG`wU&gE1ey+aHc;LtQpfBRlkx_BjiN_B+dC^s{_|ZOjn(I7n&%u&nKa!ug<28Lg
zSu^Zn(|neAbV2;oO&%W%yVx7wXY1aTdfk(n{E`+~$Iv81Tj(v1vXx6t7mdgdSAKraqs_|ATlwx96j0J=_B8rRHO!&)0_H
z`#-CnPxdM<&Q7e?LDmZP2BY>*TT5grk#`Tevml&5F{V_BII0W_vBZ|efiTre1gRDIT-oZ
zt3xAZbwJ{_$Gc~onG?qS8jN@9+Zy^-9cBMPADpeOrM{z|*IVCF2fC)8T-QV2KZ5ao
zoWFlkx7K%O$;X?&y;x6zoBZA<>L~iA4)o36lxSds?|mYFS-;7T&gmcPad4C0`$Qdf
z&dcvx?C){f-$L(wqD~tx6tS%f=|uZF`q+f`fid1c6kXVP5lzHO81A%6f$#
z>($WxzFzJ6mvi_Y-@Ag;!#R`uFyhw8Z|_}Mr|^SA?@5Pa>d#(3(;8>Je-%`_oOOps
zT(3s_Ww$uBPaf)kai9JZZ`3&yJLl2JZ|zF|(f-i$o{xUu7mPaB=ugo%eyn%ILE2+I
zqjg}eI)Vh5k|#fCmuiSd>e(2nNOgflTJDJpjF3ArgPHf6w^obvO8hOigG4hS;&^YV;tDxFNpQB&9K8<5;
zN1wD$o}S4R0`CvN;XQCHz7`Xc+@dp+K`>~ZMJ+EHF>SNTf&4|?35|0qs=g}F}E+pCl4
zPthU$L5E{EyZ)$;^WEOvuEQX8qCfH*bKDyFZCybpk`{ai=WIM}+vd6V&k_&=g_I^_MiBJM=PfQ3icB${#y%6Z(&<5I@;&I_~jC%`^G0@?#vBry%jne_`Zb+0QffJa_AP<99f&^84lcK0oF6P4#&T|9%?%
zDf32un73>6`)TAa^G1H=gWnOEhu|jvej0Vyx{`mlv~`~LS?{;V@262`*)O*B@|h0m?8QEH
z@SLxo#sz&>ZLFV%&ba;1oAT3MVw692;trkkJcamS*O*v5T=qCv^3$&JmG-q35O-kF
z{R?Mh*QI(_?|VDzzZ>Zf>*s-weZQkV_Ps+NY2DMlSEzc~@5pbAxaRyt-{fcgB#!kn
zNWaA%9rzfK*jm(*cYEcziH(hlcoqsEr@@e7(AKh?o`
zI!HYFEsXpt>o{in@3Hg_|GtFZl@1@x{ByGFaON#PaeHujQnz*XFwUoR%ZvIB<;PWc
z!Q-YciwpA4v^>l1hkj^>`-M@*(G~iLdTl*N7t{;M$GlTVzs?NCE27#*FVpwCefoL%
zeXj3N{@9J`4|(X1G488gix<%waj@j4UFD1R4}anL4!`Ptg}F}E+pG8JkDV9L7yU76
zJgQl*&-k9}YC5PoIY*P<7;(+{ZGO=Q`Hjktju>x9{n&$y!(hwDgZ-WU8s!)MMvX6V
z%q#B|f|loM&L`3i_Y0$r=6Y>@cRc3xLh|u$kvh7{Wz<+Rzg>}e#LoQiF5D=8?8MO@
z@)Y8S{c?^Mcb?XF*{M3G~qp41NZg~!<)2O`Yd`5YVZ;8_XOt9_G
z5&3zZO58g0h2HQ(U&KM`#LhUNe~2E<{#DO?)nW0f3mp^Bb7E8+<6!af!%lqUfyIyZ
zy^f}Fu=7v%{YKcZoMDj(;0WyfN%K
Jz9Tuc)3=nOb|C-&
literal 0
HcmV?d00001
From 02f96f022af7895a4cb8be44a62e22d0356b79c5 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 16:37:58 +0100
Subject: [PATCH 20/29] WIP: added brackets for clarity in mapping expressions.
---
src/buddies/src/bd/bdReaderOptions.cc | 32 +++++++++++++++++--------
src/db/db/dbStreamLayers.cc | 30 ++++++++++++++++++++++-
src/db/unit_tests/dbStreamLayerTests.cc | 19 +++++++++++++++
src/lay/lay/doc/about/layer_mapping.xml | 25 +++++++++++++++++++
4 files changed, 95 insertions(+), 11 deletions(-)
diff --git a/src/buddies/src/bd/bdReaderOptions.cc b/src/buddies/src/bd/bdReaderOptions.cc
index 156e06048..6367fa374 100644
--- a/src/buddies/src/bd/bdReaderOptions.cc
+++ b/src/buddies/src/bd/bdReaderOptions.cc
@@ -155,32 +155,44 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"layer is specified, all source layers addressed with the source specification are "
"combined into this target layer.\n"
"\n"
+ "For clarity, source and target specifications can be enclosed in round or square brackets. "
+ "With square brackets, the default target is '*/*' which results in the expansion of a source "
+ "layer range.\n"
+ "\n"
"To clone layers, add a mapping statement beginning with a '+' character. While other mapping statements "
"redefine mappings established before, mapping statement starting with '+' will clone the layer (1:m mapping).\n"
"\n"
- "It's also possible to cancel mappings established before by using an 'unmap' statement. Such a statement "
+ "You can cancel mappings established before by using an 'unmap' statement. Such a statement "
"begins with a '-' and lists the layers whose mapping is to be removed. This is useful for creating "
"'mapping holes' in sequences.\n"
"\n"
+ "If brackets are used, '+' (multi-mapping) and '-' (unmapping) needs to go before the brackets.\n"
+ "\n"
"Examples:\n"
"\n"
"* 1/0 2/0 3/0-255:17/0\n"
- " Selects 1/0, 2/0 and maps layer 3, datatype 0 to 255 to layer 17, datatype 0\n"
+ " Selects 1/0, 2/0 and maps layer 3, datatype 0 to 255 to layer 17, datatype 0.\n"
+ " If clarity, the mapping can also be written with brackets like this: '(1/0) (2/0) (3/0-255:17/0)'.\n"
"\n"
"* A:1/0 B:2/0\n"
- " Maps named layer A to 1/0 and named layer B to 2/0"
+ " Maps named layer A to 1/0 and named layer B to 2/0.\n"
+ " If clarity, the mapping can also be written with brackets like this: '(A:1/0) (B:2/0)'.\n"
"\n"
- "* */*:*/* +10/*:1000/*"
- " Includes all layers, but in addition copy all layers 10 to 1000 while keeping the datatype\n"
+ "* [*/*] +(10/*:1000)/*\n"
+ " Includes all layers, but in addition copies all datatypes of layer 10 to 1000 while keeping the datatype.\n"
+ " Note the square bracket which implies range expansion and how the brackets give a visual aid for the "
+ " grouping of the mapping parts.\n"
"\n"
- "* */*:*/* -10/*"
- " Includes all layers, but drops layer 10, all datatypes."
+ "* [*/*] -(10/*)\n"
+ " Includes all layers, but drops all datatypes from layer 10 through 'unmapping'.\n"
+ " Please note, that this specification requires -" + m_prefix + "s (skip unknown layers) because otherwise the "
+ " unmapped layers are still created through the unknown layer fallback path.\n"
)
<< tl::arg (group +
"--" + m_long_prefix + "layer-map-file=map", this, &GenericReaderOptions::set_layer_map_file, "Specifies the layer mapping for the input as a file",
- "This option specifies the layer selection or mapping like + -" + m_prefix + ", but takes the mapping for the given file. "
- "Each line in this file is read as one layer mapping expression. Empty lines or lines starting with a hash (#) character are "
- "ignored."
+ "This option specifies the layer selection or mapping like -" + m_prefix + "m, but takes the mapping from the given file. "
+ "Each line in this file is read as one layer mapping expression. "
+ "Empty lines or lines starting with a hash (#) character or with double slashes (//) are ignored."
)
;
}
diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc
index ac2cc9819..52c14a679 100644
--- a/src/db/db/dbStreamLayers.cc
+++ b/src/db/db/dbStreamLayers.cc
@@ -635,6 +635,13 @@ LayerMap::mmap_expr (tl::Extractor &ex, unsigned int l)
{
try {
+ bool round_bracket = false, square_bracket = false;
+ if (ex.test ("(")) {
+ round_bracket = true;
+ } else if (ex.test ("[")) {
+ square_bracket = true;
+ }
+
do {
tl::Extractor ex_saved = ex;
@@ -678,7 +685,15 @@ LayerMap::mmap_expr (tl::Extractor &ex, unsigned int l)
LayerProperties lp;
lp.read (ex, true);
m_target_layers[l] = lp;
- }
+ } else if (square_bracket) {
+ m_target_layers[l] = LayerProperties (db::any_ld (), db::any_ld ());
+ }
+
+ if (round_bracket) {
+ ex.expect (")");
+ } else if (square_bracket) {
+ ex.expect ("]");
+ }
} catch (...) {
throw LayerSpecFormatException (ex.skip ());
@@ -790,6 +805,13 @@ LayerMap::unmap_expr (tl::Extractor &ex)
{
try {
+ bool round_bracket = false, square_bracket = false;
+ if (ex.test ("(")) {
+ round_bracket = true;
+ } else if (ex.test ("[")) {
+ square_bracket = true;
+ }
+
do {
tl::Extractor ex_saved = ex;
@@ -829,6 +851,12 @@ LayerMap::unmap_expr (tl::Extractor &ex)
lp.read (ex, true);
}
+ if (round_bracket) {
+ ex.expect (")");
+ } else if (square_bracket) {
+ ex.expect ("]");
+ }
+
} catch (...) {
throw LayerSpecFormatException (ex.skip ());
}
diff --git a/src/db/unit_tests/dbStreamLayerTests.cc b/src/db/unit_tests/dbStreamLayerTests.cc
index f031de1f3..81d6ab21a 100644
--- a/src/db/unit_tests/dbStreamLayerTests.cc
+++ b/src/db/unit_tests/dbStreamLayerTests.cc
@@ -74,6 +74,25 @@ TEST(1)
EXPECT_EQ (lm.first_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");
+
+ // brackets, "add_expr"
+ lm.clear ();
+ lm.add_expr ("[1-10/*]", 1);
+ EXPECT_EQ (lm.mapping_str (1), "1-10/* : */*");
+ lm.add_expr ("-(5/*)", 0);
+ EXPECT_EQ (lm.mapping_str (1), "1-4/*;6-10/* : */*");
+
+ lm.clear ();
+ lm.add_expr ("[1/15]", 1);
+ lm.add_expr ("+(1/5:1001/5)", 1);
+ // NOTE: the target is taken from the second expression (the last one wins)
+ EXPECT_EQ (lm.mapping_str (1), "1/5,15 : 1001/5");
+
+ lm.clear ();
+ lm.add_expr ("+(1/5:1001/5)", 1);
+ lm.add_expr ("[1/15]", 1);
+ // NOTE: the target is taken from the second expression (the last one wins)
+ EXPECT_EQ (lm.mapping_str (1), "1/5,15 : */*");
}
TEST(2)
diff --git a/src/lay/lay/doc/about/layer_mapping.xml b/src/lay/lay/doc/about/layer_mapping.xml
index 2f3ea4c82..4376bc1e5 100644
--- a/src/lay/lay/doc/about/layer_mapping.xml
+++ b/src/lay/lay/doc/about/layer_mapping.xml
@@ -201,5 +201,30 @@
when using unmapping and multi-mapping.
+ Brackets
+
+
+ Square brackets can be used to imply mapping to the original layer. When putting square brackets
+ around a mapping expression, the default target is "*/*", which means expansion to the original layer.
+ Hence the following statements are identical:
+
+
+ [1-10/*]
+1-10/* : */*
+
+
+
+ When combining this with "+" for multi-mapping, put "+" in front of the bracket.
+
+
+
+ You can put round brackets around mapping expressions for visual clarity, specifically when
+ combining them with "-" (unmapping) or "+" (multi-mapping):
+
+
+ -(1-10/*)
++(17/0 : 1017/0)
+
+
From 2b61b481641dc9c5cf08d7f9fdc3b00797b03115 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 18:25:53 +0100
Subject: [PATCH 21/29] WIP: multi-mapping for named layer readers, bugfix for
GDS/OASIS
---
src/db/db/dbCommonReader.cc | 29 ++----
src/db/db/dbNamedLayerReader.cc | 92 +++++++++++++++---
src/db/db/dbNamedLayerReader.h | 13 ++-
.../streamers/cif/db_plugin/dbCIFReader.cc | 10 +-
.../streamers/cif/unit_tests/dbCIFReader.cc | 12 +--
.../streamers/dxf/db_plugin/dbDXFReader.cc | 21 ++--
.../streamers/gds2/unit_tests/dbGDS2Reader.cc | 41 ++++++++
.../streamers/magic/db_plugin/dbMAGReader.cc | 10 +-
testdata/gds/alm_au2.gds | Bin 11842 -> 8906 bytes
9 files changed, 155 insertions(+), 73 deletions(-)
diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc
index 59d59f16f..0bf21814a 100644
--- a/src/db/db/dbCommonReader.cc
+++ b/src/db/db/dbCommonReader.cc
@@ -560,31 +560,14 @@ CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl)
} else {
+ for (std::set::const_iterator i = li.begin (); i != li.end (); ++i) {
+ m_layer_map_out.mmap (dl, *i, layout.get_properties (*i));
+ }
+
std::map, unsigned int>::iterator mmp = m_multi_mapping_placeholders.find (li);
if (mmp == m_multi_mapping_placeholders.end ()) {
-
- // multi-mapping: create a placeholder layer if required
-
- for (std::set::const_iterator i = li.begin (); i != li.end (); ++i) {
- m_layer_map_out.mmap (dl, *i, layout.get_properties (*i));
- }
-
- for (std::set::const_iterator i = li.begin (); i != li.end (); ++i) {
- std::set sl;
- sl.insert (*i);
- if (m_multi_mapping_placeholders.find (sl) == m_multi_mapping_placeholders.end ()) {
- // a layer not used in a single-target context can be used as a placeholder layer (but only once)
- m_multi_mapping_placeholders.insert (std::make_pair (sl, *i));
- mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, *i)).first;
- break;
- }
- }
-
- if (mmp == m_multi_mapping_placeholders.end ()) {
- // create a placeholder layer for later
- mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, layout.insert_layer ())).first;
- }
-
+ // create a placeholder layer
+ mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, layout.insert_layer ())).first;
}
return std::make_pair (true, mmp->second);
diff --git a/src/db/db/dbNamedLayerReader.cc b/src/db/db/dbNamedLayerReader.cc
index adff2797f..9716f4cab 100644
--- a/src/db/db/dbNamedLayerReader.cc
+++ b/src/db/db/dbNamedLayerReader.cc
@@ -122,21 +122,32 @@ extract_ld (const char *s, int &l, int &d, std::string &n)
std::pair
NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
+{
+ std::map >::const_iterator lc = m_layer_cache.find (n);
+ if (lc != m_layer_cache.end ()) {
+ return lc->second;
+ } else {
+ std::pair res = open_layer_uncached (layout, n);
+ m_layer_cache.insert (std::make_pair (n, res));
+ return res;
+ }
+}
+
+std::pair
+NamedLayerReader::open_layer_uncached (db::Layout &layout, const std::string &n)
{
int l = -1, d = -1;
std::string on;
- std::pair ll (false, 0);
-
- ll = m_layer_map.first_logical (n, layout);
- if (! ll.first && !m_keep_layer_names) {
+ std::set li = m_layer_map.logical (n, layout);
+ if (li.empty () && ! m_keep_layer_names) {
if (extract_plain_layer (n.c_str (), l)) {
db::LayerProperties lp;
lp.layer = l;
lp.datatype = 0;
- ll = m_layer_map.first_logical (lp, layout);
+ li = m_layer_map.logical (lp, layout);
} else if (extract_ld (n.c_str (), l, d, on)) {
@@ -144,20 +155,33 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
lp.layer = l;
lp.datatype = d;
lp.name = on;
- ll = m_layer_map.first_logical (lp, layout);
+ li = m_layer_map.logical (lp, layout);
}
}
- if (ll.first) {
+ if (! li.empty ()) {
- // create the layer if it is not part of the layout yet.
- if (! layout.is_valid_layer (ll.second)) {
- layout.insert_layer (ll.second, m_layer_map.mapping (ll.second));
+ for (std::set::const_iterator i = li.begin (); i != li.end (); ++i) {
+ m_layer_map_out.mmap (n, *i, layout.get_properties (*i));
}
- return ll;
+ if (li.size () == 1) {
+
+ return std::make_pair (true, *li.begin ());
+
+ } else {
+
+ std::map, unsigned int>::iterator mmp = m_multi_mapping_placeholders.find (li);
+ if (mmp == m_multi_mapping_placeholders.end ()) {
+ // create a placeholder layer for later
+ mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, layout.insert_layer ())).first;
+ }
+
+ return std::make_pair (true, mmp->second);
+
+ }
} else if (! m_create_layers) {
@@ -188,21 +212,61 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
void
NamedLayerReader::map_layer (const std::string &name, unsigned int layer)
{
- m_layer_map.map (name, layer);
+ m_layer_map_out.map (name, layer);
}
void
-NamedLayerReader::prepare_layers ()
+NamedLayerReader::prepare_layers (db::Layout &layout)
{
m_new_layers.clear ();
m_next_layer_index = m_layer_map.next_index ();
+
+ m_layer_map_out.clear ();
+ m_multi_mapping_placeholders.clear ();
+ m_layer_cache.clear ();
+
+ m_layer_map.prepare (layout);
+
+ // create a pseudo-multimapping for single targets
+ for (db::LayerMap::const_iterator_layers li = m_layer_map.begin (); li != m_layer_map.end (); ++li) {
+ for (db::LayerMap::const_iterator_datatypes di = li->second.begin (); di != li->second.end (); ++di) {
+ if (di->second.size () == 1) {
+ m_multi_mapping_placeholders.insert (std::make_pair (di->second, *di->second.begin ()));
+ }
+ }
+ }
}
void
NamedLayerReader::finish_layers (db::Layout &layout)
{
+ // resolve layer multi-mapping
+
+ for (std::map, unsigned int>::const_iterator i = m_multi_mapping_placeholders.begin (); i != m_multi_mapping_placeholders.end (); ++i) {
+
+ if (i->first.size () > 1) {
+
+ bool discard_layer = i->first.find (i->second) == i->first.end ();
+
+ for (std::set::const_iterator l = i->first.begin (); l != i->first.end (); ++l) {
+
+ // last one? this one will get a "move"
+ std::set::const_iterator ll = l;
+ if (discard_layer && ++ll == i->first.end ()) {
+ layout.move_layer (i->second, *l);
+ layout.delete_layer (i->second);
+ } else {
+ layout.copy_layer (i->second, *l);
+ }
+
+ }
+
+ }
+
+ }
+
// assign layer numbers to new layers
- if (! m_new_layers.empty () && !m_keep_layer_names) {
+ if (! m_new_layers.empty () && ! m_keep_layer_names) {
std::set > used_ld;
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
diff --git a/src/db/db/dbNamedLayerReader.h b/src/db/db/dbNamedLayerReader.h
index d3b677111..53c68d9f4 100644
--- a/src/db/db/dbNamedLayerReader.h
+++ b/src/db/db/dbNamedLayerReader.h
@@ -54,6 +54,7 @@ public:
*/
NamedLayerReader ();
+protected:
/**
* @brief Sets a value indicating whether to create new layers
*/
@@ -75,9 +76,9 @@ public:
/**
* @brief Gets the layer map
*/
- const LayerMap &layer_map ()
+ const LayerMap &layer_map_out ()
{
- return m_layer_map;
+ return m_layer_map_out;
}
/**
@@ -96,7 +97,6 @@ public:
return m_keep_layer_names;
}
-protected:
/**
* @brief Opens a new layer
* This method will create or locate a layer for a given name.
@@ -121,7 +121,7 @@ protected:
* @brief Prepares reading
* This method must be called before the reading is done.
*/
- void prepare_layers ();
+ void prepare_layers (db::Layout &layout);
private:
bool m_create_layers;
@@ -129,6 +129,11 @@ private:
LayerMap m_layer_map;
unsigned int m_next_layer_index;
std::map m_new_layers;
+ db::LayerMap m_layer_map_out;
+ std::map > m_layer_cache;
+ std::map, unsigned int> m_multi_mapping_placeholders;
+
+ std::pair open_layer_uncached (db::Layout &layout, const std::string &name);
};
}
diff --git a/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc b/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc
index 2f0f4f28d..057ff47f3 100644
--- a/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc
+++ b/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc
@@ -59,22 +59,20 @@ CIFReader::~CIFReader ()
const LayerMap &
CIFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
- prepare_layers ();
-
const db::CIFReaderOptions &specific_options = options.get_options ();
m_wire_mode = specific_options.wire_mode;
m_dbu = specific_options.dbu;
- db::LayerMap lm = specific_options.layer_map;
- lm.prepare (layout);
- set_layer_map (lm);
+ set_layer_map (specific_options.layer_map);
set_create_layers (specific_options.create_other_layers);
set_keep_layer_names (specific_options.keep_layer_names);
+ prepare_layers (layout);
+
do_read (layout);
finish_layers (layout);
- return layer_map ();
+ return layer_map_out ();
}
const LayerMap &
diff --git a/src/plugins/streamers/cif/unit_tests/dbCIFReader.cc b/src/plugins/streamers/cif/unit_tests/dbCIFReader.cc
index 7b74f0846..2d41920e8 100644
--- a/src/plugins/streamers/cif/unit_tests/dbCIFReader.cc
+++ b/src/plugins/streamers/cif/unit_tests/dbCIFReader.cc
@@ -39,13 +39,8 @@ static void run_test (tl::TestBase *_this, const std::string &base, const char *
unsigned int ln = 0;
tl::Extractor ex (map);
while (! ex.at_end ()) {
- std::string n;
- int l;
- ex.read_word_or_quoted (n);
- ex.test (":");
- ex.read (l);
+ lm.add_expr (ex, ln++);
ex.test (",");
- lm.map (n, ln++, db::LayerProperties (l, 0));
}
opt->layer_map = lm;
opt->create_other_layers = true;
@@ -173,6 +168,11 @@ TEST(3b)
run_test (_this, tl::testsrc_private (), "t3.cif.gz", "t3b_au.gds.gz", "CAA:43,CCA:48,CCP:47,CMF:49,CMS:51,CPG:46,CSN:45,CSP:44,CVA:50,CWN:42,XP:26", 0.00012);
}
+TEST(3c)
+{
+ run_test (_this, tl::testsrc_private (), "t3.cif.gz", "t3c_au.gds.gz", "(CPG:1/0) +(CPG:1000/0) (CCP:1/0) (CMF:2/0) +(CMF:1000/0) (CVA:3/0)", 0.00012);
+}
+
TEST(4)
{
run_test (_this, tl::testsrc_private (), "t4.cif.gz", "t4_au.gds.gz");
diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
index 5517001d8..2335d238d 100644
--- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
+++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
@@ -318,9 +318,7 @@ DXFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
m_stream.reset ();
m_initial = true;
m_line_number = 0;
- db::LayerMap lm = specific_options.layer_map;
- lm.prepare (layout);
- set_layer_map (lm);
+ set_layer_map (specific_options.layer_map);
set_create_layers (specific_options.create_other_layers);
set_keep_layer_names (specific_options.keep_layer_names);
@@ -330,7 +328,7 @@ DXFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
do_read (layout, top);
cleanup (layout, top);
- return layer_map ();
+ return layer_map_out ();
}
const LayerMap &
@@ -379,29 +377,24 @@ DXFReader::open_layer (db::Layout &layout, const std::string &n)
void
DXFReader::do_read (db::Layout &layout, db::cell_index_type top)
{
+ prepare_layers (layout);
+
// 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 ().first_logical (zero_layer_name, layout);
+ std::pair ll = open_layer (layout, zero_layer_name);
if (ll.first) {
- // create the layer if it is not part of the layout yet.
- if (! layout.is_valid_layer (ll.second)) {
- layout.insert_layer (ll.second, layer_map ().mapping (ll.second));
- }
-
+ // layer exists
m_zero_layer = ll.second;
} else {
// or explicitly create the layer:
- m_zero_layer = layer_map ().next_index ();
- layout.insert_layer (m_zero_layer, db::LayerProperties (0, 0, zero_layer_name));
+ m_zero_layer = layout.insert_layer (db::LayerProperties (0, 0, zero_layer_name));
map_layer (zero_layer_name, m_zero_layer);
}
- prepare_layers ();
-
// Read sections
int g;
diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
index d045b10d3..6a70c0821 100644
--- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
+++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc
@@ -476,6 +476,47 @@ TEST(3_MultiMapping)
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}
+TEST(3_MultiMapping2)
+{
+ db::Manager m (false);
+ db::Layout layout (&m);
+
+ db::LoadLayoutOptions options;
+ db::LayerMap lm, lm_read;
+
+ unsigned int n = 0;
+ lm.add_expr ("(1/0:1/0)", n++);
+ lm.add_expr ("+(1/0:1000/0)", n++);
+ lm.add_expr ("(4/0:1/0)", n++);
+ lm.add_expr ("(2/0:2/0)", n++);
+ lm.add_expr ("+(2/0:1000/0)", n++);
+ lm.add_expr ("(3/0:3/0)", n++);
+ options.get_options ().layer_map = lm;
+
+ {
+ tl::InputStream file (tl::testsrc () + "/testdata/gds/t10.gds");
+ db::Reader reader (file);
+ lm_read = reader.read (layout, options);
+ }
+
+ EXPECT_EQ (lm_read.to_string_file_format (),
+ "+1/0;4/0 : 1/0\n"
+ "+1-2/0 : 1000/0\n"
+ "+2/0 : 2/0\n"
+ "3/0 : 3/0\n"
+ "6/0 : 6/0\n"
+ "8/0 : 8/0\n"
+ "5/0 : 5/0\n"
+ "7/0 : 7/0\n"
+ "3/1 : 3/1\n"
+ "6/1 : 6/1\n"
+ "8/1 : 8/1\n"
+ );
+
+ std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au3.gds");
+ db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
+}
+
TEST(4_CollectModeRename)
{
db::Manager m (false);
diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc
index f60be213e..b19aa1c78 100644
--- a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc
+++ b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc
@@ -72,8 +72,6 @@ MAGReader::read (db::Layout &layout)
const LayerMap &
MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
- prepare_layers ();
-
mp_klayout_tech = 0;
std::string klayout_tech_name = layout.meta_info_value ("technology");
if (! klayout_tech_name.empty () && db::Technologies::instance ()->has_technology (klayout_tech_name)) {
@@ -87,9 +85,7 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
m_merge = specific_options.merge;
mp_current_stream = 0;
- db::LayerMap lm = specific_options.layer_map;
- lm.prepare (layout);
- set_layer_map (lm);
+ set_layer_map (specific_options.layer_map);
set_create_layers (specific_options.create_other_layers);
set_keep_layer_names (specific_options.keep_layer_names);
@@ -110,6 +106,8 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
m_dbu_trans_inv = db::CplxTrans (m_dbu).inverted ();
m_tech.clear ();
+ prepare_layers (layout);
+
{
tl::SelfTimer timer (tl::verbosity () >= 11, "Reading MAGIC file tree");
@@ -129,7 +127,7 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
}
finish_layers (layout);
- return layer_map ();
+ return layer_map_out ();
}
void
diff --git a/testdata/gds/alm_au2.gds b/testdata/gds/alm_au2.gds
index 4492ec4d999fe06e34e1a83c544f52a0f82083d4..c1267e0bde4e5045028ad455cd2b09dc8552b411 100644
GIT binary patch
delta 92
zcmX>UbIMhTfsKKQDS|0Kob6jBDoXxYA
YadLqG$0osM=FPXo0=PGyRw?HM0QaL5Q~&?~
delta 122
zcmX@*dMHMTfsKKQDS|0L%S
Date: Sat, 19 Dec 2020 19:42:40 +0100
Subject: [PATCH 22/29] WIP: LEF/DEF multi-mapping.
---
.../lefdef/db_plugin/dbDEFImporter.cc | 86 +++----
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 210 +++++++++++-------
.../lefdef/db_plugin/dbLEFDEFImporter.h | 8 +-
3 files changed, 176 insertions(+), 128 deletions(-)
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc
index 4dc1d25ac..3917c4c85 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc
@@ -157,14 +157,14 @@ DEFImporter::read_diearea (db::Layout &layout, db::Cell &design, double scale)
if (points.size () >= 2) {
// create outline shape
- std::pair dl = open_layer (layout, std::string (), Outline, 0);
- if (dl.first) {
+ std::set dl = open_layer (layout, std::string (), Outline, 0);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
if (points.size () == 2) {
- design.shapes (dl.second).insert (db::Box (points [0], points [1]));
+ design.shapes (*l).insert (db::Box (points [0], points [1]));
} else {
db::Polygon p;
p.assign_hull (points.begin (), points.end ());
- design.shapes (dl.second).insert (p);
+ design.shapes (*l).insert (p);
}
}
@@ -305,9 +305,9 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale)
db::Polygon p;
read_polygon (p, scale);
- std::pair dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage, 0);
- if (dl.first) {
- design.shapes (dl.second).insert (p);
+ std::set dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage, 0);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ design.shapes (*l).insert (p);
}
} else if (test ("RECT")) {
@@ -315,9 +315,9 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale)
db::Polygon p;
read_rect (p, scale);
- std::pair dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage, 0);
- if (dl.first) {
- design.shapes (dl.second).insert (p);
+ std::set dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage, 0);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ design.shapes (*l).insert (p);
}
} else {
@@ -554,17 +554,19 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
test (")");
- std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
- if (dl.first) {
+ std::set dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
+ if (! dl.empty ()) {
db::Point p (x, y);
db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)),
db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale)));
- if (prop_id != 0) {
- design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id));
- } else {
- design.shapes (dl.second).insert (rect);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ if (prop_id != 0) {
+ design.shapes (*l).insert (db::object_with_properties (rect, prop_id));
+ } else {
+ design.shapes (*l).insert (rect);
+ }
}
}
@@ -615,9 +617,9 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
}
if (pts.size () > 1) {
- std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
- if (dl.first) {
- produce_routing_geometry (design, style, dl.second, prop_id, pts, ext, w);
+ std::set dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ produce_routing_geometry (design, style, *l, prop_id, pts, ext, w);
}
}
@@ -803,12 +805,12 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool
db::Polygon p;
read_polygon (p, scale);
- std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
- if (dl.first) {
+ std::set dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
if (prop_id != 0) {
- design.shapes (dl.second).insert (db::object_with_properties (p, prop_id));
+ design.shapes (*l).insert (db::object_with_properties (p, prop_id));
} else {
- design.shapes (dl.second).insert (p);
+ design.shapes (*l).insert (p);
}
}
@@ -821,12 +823,12 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool
db::Polygon p;
read_rect (p, scale);
- std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
- if (dl.first) {
+ std::set dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
if (prop_id != 0) {
- design.shapes (dl.second).insert (db::object_with_properties (p, prop_id));
+ design.shapes (*l).insert (db::object_with_properties (p, prop_id));
} else {
- design.shapes (dl.second).insert (p);
+ design.shapes (*l).insert (p);
}
}
@@ -1191,8 +1193,8 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
// Produce geometry collected so far
for (std::map, std::vector >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) {
- std::pair dl = open_layer (layout, g->first.first, Pins, g->first.second);
- if (dl.first) {
+ std::set dl = open_layer (layout, g->first.first, Pins, g->first.second);
+ if (! dl.empty ()) {
db::properties_id_type prop_id = 0;
if (produce_pin_props ()) {
@@ -1204,21 +1206,27 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) {
db::Polygon pt = p->transformed (trans);
if (prop_id == 0) {
- design.shapes (dl.second).insert (pt);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ design.shapes (*l).insert (pt);
+ }
} else {
- design.shapes (dl.second).insert (db::PolygonWithProperties (pt, prop_id));
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ design.shapes (*l).insert (db::PolygonWithProperties (pt, prop_id));
+ }
}
}
}
dl = open_layer (layout, g->first.first, Label, 0);
- if (dl.first) {
+ if (! dl.empty ()) {
db::Box bbox;
if (! g->second.empty ()) {
bbox = g->second.back ().box ().transformed (trans);
}
- design.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (db::Vector (bbox.center ()))));
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ design.shapes (*l).insert (db::Text (label.c_str (), db::Trans (db::Vector (bbox.center ()))));
+ }
}
}
@@ -1554,10 +1562,10 @@ DEFImporter::do_read (db::Layout &layout)
} else {
- std::pair dl = open_layer (layout, std::string (), Regions, 0);
- if (dl.first) {
+ std::set dl = open_layer (layout, std::string (), Regions, 0);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) {
- group_cell->shapes (dl.second).insert (*p);
+ group_cell->shapes (*l).insert (*p);
}
}
regions.erase (r);
@@ -1597,12 +1605,12 @@ DEFImporter::do_read (db::Layout &layout)
if (! regions.empty ()) {
- std::pair dl = open_layer (layout, std::string (), Regions, 0);
- if (dl.first) {
+ std::set dl = open_layer (layout, std::string (), Regions, 0);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
for (std::map >::const_iterator r = regions.begin (); r != regions.end (); ++r) {
for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) {
- others_cell->shapes (dl.second).insert (*p);
+ others_cell->shapes (*l).insert (*p);
}
}
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index f68700609..f8f6b0d4d 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -146,16 +146,16 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
db::Vector vs ((m_cutsize.x () * m_columns + m_cutspacing.x () * (m_columns - 1)) / 2, (m_cutsize.y () * m_rows + m_cutspacing.y () * (m_rows - 1)) / 2);
db::Box via_box (m_offset - vs, m_offset + vs);
- std::pair dl (false, 0);
+ std::set dl;
dl = reader.open_layer (layout, m_bottom_layer, ViaGeometry, mask_bottom);
- if (dl.first) {
- cell.shapes (dl.second).insert (db::Polygon (via_box.enlarged (m_be).moved (m_bo)));
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_be).moved (m_bo)));
}
dl = reader.open_layer (layout, m_top_layer, ViaGeometry, mask_top);
- if (dl.first) {
- cell.shapes (dl.second).insert (db::Polygon (via_box.enlarged (m_te).moved (m_bo)));
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_bo)));
}
const char *p = m_pattern.c_str ();
@@ -253,8 +253,8 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
}
dl = reader.open_layer (layout, m_cut_layer, ViaGeometry, cm);
- if (dl.first) {
- cell.shapes (dl.second).insert (db::Polygon (vb));
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ cell.shapes (*l).insert (db::Polygon (vb));
}
}
@@ -322,9 +322,9 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la
unsigned int mshift = get_maskshift (g->first.first, ext_msl, masks);
unsigned int mask = mask_for (g->first.first, g->first.second.second, mshift, nm);
- std::pair dl = reader.open_layer (layout, g->first.first, g->first.second.first, mask);
- if (dl.first) {
- cell.shapes (dl.second).insert (g->second);
+ std::set dl = reader.open_layer (layout, g->first.first, g->first.second.first, mask);
+ for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) {
+ cell.shapes (*l).insert (g->second);
}
}
@@ -809,7 +809,9 @@ void
LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, const db::LayerProperties &lp, unsigned int layer, unsigned int mask)
{
tl_assert (m_has_explicit_layer_mapping);
- m_layers [std::make_pair (n, std::make_pair (purpose, mask))] = std::make_pair (true, layer);
+ std::set ll;
+ ll.insert (layer);
+ m_layers [std::make_pair (n, std::make_pair (purpose, mask))] = ll;
m_layer_map.map (lp, layer);
}
@@ -1040,13 +1042,13 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
}
}
-std::pair
+std::set
LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose, unsigned int mask)
{
- std::map >, std::pair >::const_iterator nl = m_layers.find (std::make_pair (n, std::make_pair (purpose, mask)));
+ std::map >, std::set >::const_iterator nl = m_layers.find (std::make_pair (n, std::make_pair (purpose, mask)));
if (nl == m_layers.end ()) {
- std::pair ll (false, 0);
+ std::set ll;
if (n.empty () || ! m_has_explicit_layer_mapping) {
ll = open_layer_uncached (layout, n, purpose, mask);
@@ -1134,8 +1136,7 @@ static std::string purpose_to_name (LayerPurpose purpose)
* 4/17 4/17 : 4/11 OUTLINE 4/11
*/
-std::pair
-LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n, LayerPurpose purpose, unsigned int mask)
+std::set LEFDEFReaderState::open_layer_uncached(db::Layout &layout, const std::string &n, LayerPurpose purpose, unsigned int mask)
{
if (n.empty ()) {
@@ -1154,7 +1155,7 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
}
if (! produce) {
- return std::make_pair (false, 0);
+ return std::set ();
}
db::LayerProperties lp;
@@ -1180,35 +1181,55 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
}
// employ the layer map to find the target layer
- std::pair ll = m_layer_map.first_logical (lp, layout);
+ std::set ll = m_layer_map.logical (lp, layout);
+ if (ll.empty () && ! m_create_layers) {
+ return std::set ();
+ }
- if (ll.first) {
+ std::set res;
+
+ // map the layers to targets from the layout
+ // (NOTE: the other readers will do this in advance, but LEF/DEF is too dynamic)
+
+ bool at_least_once = true;
+ for (std::set::const_iterator l = ll.begin (); l != ll.end () || at_least_once; ++l) {
+
+ at_least_once = false;
// If the layer map provides a target, use that one for the layer
- const db::LayerProperties *lpp = m_layer_map.target (ll.second);
+ db::LayerProperties lp_new = lp;
+ const db::LayerProperties *lpp = (l == ll.end () ? 0 : m_layer_map.target (*l));
if (lpp) {
if (! lpp->name.empty ()) {
- lp.name = lpp->name;
+ lp_new.name = lpp->name;
}
if (lpp->datatype >= 0) {
- lp.datatype = lpp->datatype;
+ lp_new.datatype = lpp->datatype;
}
if (lpp->layer >= 0) {
- lp.layer = lpp->layer;
+ lp_new.layer = lpp->layer;
}
}
- } else if (! m_create_layers) {
- return std::make_pair (false, 0);
- }
-
- for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
- if ((*l).second->log_equal (lp)) {
- return std::make_pair (true, (*l).first);
+ bool found = false;
+ for (db::Layout::layer_iterator i = layout.begin_layers (); i != layout.end_layers () && ! found; ++i) {
+ if ((*i).second->log_equal (lp_new)) {
+ found = true;
+ res.insert ((*i).first);
+ }
}
+
+ if (! found) {
+ res.insert (layout.insert_layer (lp_new));
+ }
+
+ if (l == ll.end ()) {
+ break;
+ }
+
}
- return std::make_pair (true, layout.insert_layer (lp));
+ return res;
} else {
@@ -1242,7 +1263,7 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
break;
}
if (! produce) {
- return std::make_pair (false, 0);
+ return std::set ();
}
}
@@ -1300,48 +1321,63 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
// Route the layer through the layer map, first the decorated name and if there is no mapping, the
// undecorated one.
- std::pair ll = m_layer_map.first_logical (name, layout);
+ std::set ll = m_layer_map.logical (name, layout);
bool generic_match = false;
- if (! ll.first) {
- ll = m_layer_map.first_logical (n, layout);
+ if (ll.empty ()) {
+ ll = m_layer_map.logical (n, layout);
generic_match = true;
} else if (n == name) {
// no suffix defined in tech component -> treat as generic match and combine datatypes
generic_match = true;
}
- if (ll.first) {
+ if (ll.empty () && ! m_create_layers) {
+ return std::set ();
+ }
+
+ std::set res;
+
+ bool at_least_once = true;
+ for (std::set::const_iterator l = ll.begin (); l != ll.end () || at_least_once; ++l) {
+
+ at_least_once = false;
// If the layer map provides a target, use that one for the layer
- // Datatypes from the target and the tech component's x_datatype specification are additive
- const db::LayerProperties *lpp = m_layer_map.target (ll.second);
+ db::LayerProperties lp_new = lp;
+ const db::LayerProperties *lpp = (l == ll.end () ? 0 : m_layer_map.target (*l));
if (lpp) {
- lp = *lpp;
- if (lp.datatype < 0) {
- lp.datatype = dt;
+ lp_new = *lpp;
+ if (lp_new.datatype < 0) {
+ lp_new.datatype = dt;
} else if (generic_match) {
- lp.datatype += dt;
+ lp_new.datatype += dt;
}
- if (lp.name.empty ()) {
- lp.name = name;
+ if (lp_new.name.empty ()) {
+ lp_new.name = name;
} else if (generic_match) {
- lp.name += name_suffix;
+ lp_new.name += name_suffix;
}
}
- } else if (! m_create_layers) {
- return std::make_pair (false, 0);
- }
-
- if (lp.layer >= 0 && lp.datatype >= 0) {
- for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
- if ((*l).second->log_equal (lp)) {
- return std::make_pair (true, (*l).first);
+ bool found = false;
+ for (db::Layout::layer_iterator i = layout.begin_layers (); i != layout.end_layers () && ! found; ++i) {
+ if ((*i).second->log_equal (lp_new)) {
+ found = true;
+ res.insert ((*i).first);
}
}
+
+ if (! found) {
+ res.insert (layout.insert_layer (lp_new));
+ }
+
+ if (l == ll.end ()) {
+ break;
+ }
+
}
- return std::make_pair (true, layout.insert_layer (lp));
+ return res;
}
}
@@ -1368,42 +1404,14 @@ LEFDEFReaderState::finish (db::Layout &layout)
db::LayerMap lm;
- for (std::map >, std::pair >::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
+ for (std::map >, std::set >::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
- if (! l->second.first) {
+ if (l->second.empty ()) {
continue;
}
std::string ps = purpose_to_name (l->first.second.first);
- unsigned int layer_index = l->second.second;
- db::LayerProperties lp = layout.get_properties (layer_index);
-
- if (lp.layer < 0) {
-
- std::map::const_iterator n4n = number_for_name.end ();
- if (! l->first.first.empty ()) {
- n4n = number_for_name.find (l->first.first);
- }
-
- if (n4n == number_for_name.end ()) {
- do {
- ++lnum;
- } while (used_numbers.find (lnum) != used_numbers.end ());
- number_for_name.insert (std::make_pair (l->first.first, lnum));
- lp.layer = lnum;
- } else {
- lp.layer = n4n->second;
- }
-
- }
-
- if (lp.datatype < 0) {
- lp.datatype = 0;
- }
-
- layout.set_properties (layer_index, lp);
-
std::string n = l->first.first;
if (! n.empty ()) {
n += ".";
@@ -1415,7 +1423,39 @@ LEFDEFReaderState::finish (db::Layout &layout)
n += tl::to_string (l->first.second.second);
}
- lm.map (db::LayerProperties (n), l->second.second, lp);
+ for (std::set::const_iterator li = l->second.begin (); li != l->second.end (); ++li) {
+
+ unsigned int layer_index = *li;
+ db::LayerProperties lp = layout.get_properties (layer_index);
+
+ if (lp.layer < 0) {
+
+ std::map::const_iterator n4n = number_for_name.end ();
+ if (! l->first.first.empty ()) {
+ n4n = number_for_name.find (l->first.first);
+ }
+
+ if (n4n == number_for_name.end ()) {
+ do {
+ ++lnum;
+ } while (used_numbers.find (lnum) != used_numbers.end ());
+ number_for_name.insert (std::make_pair (l->first.first, lnum));
+ lp.layer = lnum;
+ } else {
+ lp.layer = n4n->second;
+ }
+
+ }
+
+ if (lp.datatype < 0) {
+ lp.datatype = 0;
+ }
+
+ layout.set_properties (layer_index, lp);
+
+ lm.mmap (db::LayerProperties (n), layer_index, lp);
+
+ }
}
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
index 078361d33..f123490be 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
@@ -1054,7 +1054,7 @@ public:
/**
* @brief Create a new layer or return the index of the given layer
*/
- std::pair open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
+ std::set open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
/**
* @brief Registers a layer (assign a new default layer number)
@@ -1188,7 +1188,7 @@ private:
LEFDEFReaderState (const LEFDEFReaderState &);
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
- std::map >, std::pair > m_layers;
+ std::map >, std::set > m_layers;
db::LayerMap m_layer_map;
bool m_create_layers;
bool m_has_explicit_layer_mapping;
@@ -1201,7 +1201,7 @@ private:
std::map m_macro_generators;
std::map m_foreign_cells;
- std::pair open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
+ std::set open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
};
@@ -1364,7 +1364,7 @@ protected:
/**
* @brief Create a new layer or return the index of the given layer
*/
- std::pair open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask)
+ std::set open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask)
{
return mp_reader_state->open_layer (layout, name, purpose, mask);
}
From d4b5dab0dbda53b4856682a1765271213e2161e5 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 20:35:58 +0100
Subject: [PATCH 23/29] WIP: bugfix.
---
.../streamers/lefdef/db_plugin/dbLEFDEFImporter.cc | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index f8f6b0d4d..b4fc56598 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -1360,10 +1360,12 @@ std::set LEFDEFReaderState::open_layer_uncached(db::Layout &layout
}
bool found = false;
- for (db::Layout::layer_iterator i = layout.begin_layers (); i != layout.end_layers () && ! found; ++i) {
- if ((*i).second->log_equal (lp_new)) {
- found = true;
- res.insert ((*i).first);
+ if (lp_new.layer >= 0 && lp_new.datatype >= 0) {
+ for (db::Layout::layer_iterator i = layout.begin_layers (); i != layout.end_layers () && ! found; ++i) {
+ if ((*i).second->log_equal (lp_new)) {
+ found = true;
+ res.insert ((*i).first);
+ }
}
}
From 9688da9ffd2c97b10e006a471e766dc290db42a8 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 21:28:22 +0100
Subject: [PATCH 24/29] WIP: test for multimapping in LEF/DEF
---
src/db/db/dbCommonReader.cc | 28 ------------------
src/db/db/dbCommonReader.h | 3 --
src/db/db/dbReader.cc | 27 +++++++++++++++++
src/db/db/dbReader.h | 8 +++++
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 14 +++++----
.../lefdef/unit_tests/dbLEFDEFImportTests.cc | 18 +++++++++++
testdata/lefdef/multimap/.test.def.swp | Bin 0 -> 12288 bytes
testdata/lefdef/multimap/au.oas.gz | Bin 0 -> 598 bytes
testdata/lefdef/multimap/test.def | 28 ++++++++++++++++++
9 files changed, 90 insertions(+), 36 deletions(-)
create mode 100644 testdata/lefdef/multimap/.test.def.swp
create mode 100644 testdata/lefdef/multimap/au.oas.gz
create mode 100644 testdata/lefdef/multimap/test.def
diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc
index 0bf21814a..a64de5f72 100644
--- a/src/db/db/dbCommonReader.cc
+++ b/src/db/db/dbCommonReader.cc
@@ -32,34 +32,6 @@ namespace db
// ---------------------------------------------------------------
// Common reader implementation
-DB_PUBLIC void
-join_layer_names (std::string &s, const std::string &n)
-{
- if (s == n) {
- return;
- }
-
- if (! s.empty ()) {
-
- size_t i = s.find (n);
- if (i != std::string::npos && (i == 0 || s.c_str ()[i - 1] == ';')) {
- char after = s.c_str ()[i + n.size ()];
- if (after == 0 || after == ';') {
- // n is already contained in s
- return;
- }
- }
-
- s += ";";
-
- }
-
- s += n;
-}
-
-// ---------------------------------------------------------------
-// Common reader implementation
-
static const size_t null_id = std::numeric_limits::max ();
CommonReader::CommonReader ()
diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h
index cf53f1895..81d361672 100644
--- a/src/db/db/dbCommonReader.h
+++ b/src/db/db/dbCommonReader.h
@@ -31,9 +31,6 @@
namespace db
{
-DB_PUBLIC void
-join_layer_names (std::string &s, const std::string &n);
-
/**
* @brief The CellConflictResolution enum
*/
diff --git a/src/db/db/dbReader.cc b/src/db/db/dbReader.cc
index fc6f13adb..2ac8add6b 100644
--- a/src/db/db/dbReader.cc
+++ b/src/db/db/dbReader.cc
@@ -30,6 +30,33 @@
namespace db
{
+// ---------------------------------------------------------------
+
+DB_PUBLIC void
+join_layer_names (std::string &s, const std::string &n)
+{
+ if (s == n) {
+ return;
+ }
+
+ if (! s.empty ()) {
+
+ size_t i = s.find (n);
+ if (i != std::string::npos && (i == 0 || s.c_str ()[i - 1] == ';')) {
+ char after = s.c_str ()[i + n.size ()];
+ if (after == 0 || after == ';') {
+ // n is already contained in s
+ return;
+ }
+ }
+
+ s += ";";
+
+ }
+
+ s += n;
+}
+
// ---------------------------------------------------------------
// ReaderBase implementation
diff --git a/src/db/db/dbReader.h b/src/db/db/dbReader.h
index bab39df87..65c2ebf0d 100644
--- a/src/db/db/dbReader.h
+++ b/src/db/db/dbReader.h
@@ -54,6 +54,14 @@ public:
{ }
};
+/**
+ * @brief Joins layer names into a single, combined layer
+ * @param s The first layer name and output
+ * @param n The name to add
+ */
+DB_PUBLIC void
+join_layer_names (std::string &s, const std::string &n);
+
/**
* @brief The generic reader base class
*/
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index b4fc56598..e3a90c6ee 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -1359,18 +1359,22 @@ std::set LEFDEFReaderState::open_layer_uncached(db::Layout &layout
}
}
- bool found = false;
+ int lfound = -1;
if (lp_new.layer >= 0 && lp_new.datatype >= 0) {
- for (db::Layout::layer_iterator i = layout.begin_layers (); i != layout.end_layers () && ! found; ++i) {
+ for (db::Layout::layer_iterator i = layout.begin_layers (); i != layout.end_layers () && lfound < 0; ++i) {
if ((*i).second->log_equal (lp_new)) {
- found = true;
- res.insert ((*i).first);
+ lfound = int ((*i).first);
}
}
}
- if (! found) {
+ if (lfound < 0) {
res.insert (layout.insert_layer (lp_new));
+ } else {
+ res.insert ((unsigned int) lfound);
+ db::LayerProperties lp_org = layout.get_properties ((unsigned int) lfound);
+ join_layer_names (lp_org.name, name);
+ layout.set_properties ((unsigned int) lfound, lp_org);
}
if (l == ll.end ()) {
diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
index c46067119..eba689a5c 100644
--- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
+++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
@@ -724,6 +724,24 @@ TEST(118_density)
run_test (_this, "density", "read:in.lef", "au.oas.gz", default_options (), false);
}
+TEST(119_multimapping)
+{
+ db::LEFDEFReaderOptions options = default_options ();
+ db::LayerMap lm = db::LayerMap::from_string_file_format ("(M1:1/0)\n(M2:3/0)\n+(M1:100/0)\n+(M2:100/0)\n(VIA1:2/0)");
+ options.set_layer_map (lm);
+
+ db::LayerMap lm_read = run_test (_this, "multimap", "def:test.def", "au.oas.gz", options, false);
+ EXPECT_EQ (lm_read.to_string (),
+ "layer_map("
+ "'OUTLINE : OUTLINE (4/0)';"
+ "'+M1.VIA : M1 (1/0)';"
+ "'+M1.VIA;M2.VIA : \\'M1;M2\\' (100/0)';"
+ "'+M2.VIA : M2 (3/0)';"
+ "'VIA1.VIA : VIA1 (2/0)'"
+ ")"
+ )
+}
+
TEST(200_lefdef_plugin)
{
db::Layout ly;
diff --git a/testdata/lefdef/multimap/.test.def.swp b/testdata/lefdef/multimap/.test.def.swp
new file mode 100644
index 0000000000000000000000000000000000000000..736b58e7c8210923ca3ae77b5515507a33796e9a
GIT binary patch
literal 12288
zcmeI2F>ljA6vwZK31~sEFfcrVgc?<;?W83|ncUd4CpC6zJE>YgmXo+m)TA|uJ9GfP
z2ooQJi3N#)g$X7Q3p<|x{^ulWg{soE=$-VpefR$N-n(DCL`h3;${MXK8Uo{%5O=q}
zg&$_0&HTJNCk9cPc6-rCh0Yt@q|lF&^e{QkgxITTLT$ev9UmU0+8`RG@lZ?SQQC>p
zNbASDop@Ip9QD)QAWE{pB3Ay9n8Qqf30#1{tSA)?T^S$b?$e#yjSK8y3lm@hOn?b6
z0Vco%m;e)C0{;tvG?@{vahNNU1Kpe4Xa2fRrhH=pOn?b60Vco%m;e)C0!)AjFaajO
z1TGwU55np8MWR*FQEfS)owvNm;e)C0!)AjFaajO1egF5U;>w%fbCdh*}hzJ
zgnIO=rc+%vrQ?eQ@&mU{t^Q$q-_S;BG)%)`Jc`q>gZm!&7FEPq(Q$a5q@z4}nkTmr
z(B=;1r}kuT5VoQCKxN9ZooQd7CmXIANM|kU#`J<|JFU?$+p5zhLUlxBAYF&rS+}A<
z?QYaNFv7|Ft@|1>268S#xa(3
z3@SasB~MLh8e!*XFgPa5B?F5(t!|S6YIdEiJ_ha6;2&Ms9v(hENPpb
zZ6YIz!>q2;0%}3e7+|F$8jcKnvZNp2jj^dFtDfs1i!xQj_?5z^&`U!6_Z};&4S!Vz
ic(**Ca!;S+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I
zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>a3p7B7Q~n27ce7Od|{rB@jz@CpHiBe
zTglDt9~$E0>F3JK!py*f%;9G8HDqQ43PNdaR$oJFUnAxepb&xyRAt1>3|0lExmiGF
zGcy52;4EH7QENs9My3rc3)m(y&twv{Okretz`TL;Cd)@gQ43@VW+VwqCPty7ytuy%?AJg
literal 0
HcmV?d00001
diff --git a/testdata/lefdef/multimap/test.def b/testdata/lefdef/multimap/test.def
new file mode 100644
index 000000000..6381b8523
--- /dev/null
+++ b/testdata/lefdef/multimap/test.def
@@ -0,0 +1,28 @@
+
+VERSION 5.8 ;
+DIVIDERCHAR "/" ;
+BUSBITCHARS "[]" ;
+DESIGN chip_top ;
+UNITS DISTANCE MICRONS 1000 ;
+DIEAREA ( 30000 3000 ) ( 10000000 4000 ) ;
+VIAS 1 ;
+ - VIA1_dummy
+ + RECT M1 ( -200 -140 ) ( 200 140 )
+ + RECT VIA1 ( -100 -100 ) ( 100 100 )
+ + RECT M2 ( -300 -120 ) ( 300 120 ) ;
+END VIAS
+SPECIALNETS 1 ;
+- dummy
+ + ROUTED M1 150 + SHAPE IOWIRE ( 40000 3600 ) VIA1_dummy DO 16000 BY 1 STEP 700 0
+;
+END SPECIALNETS
+SCANCHAINS 77 ;
+- chain1_clock1
++ PARTITION clock1
++ START block1/bsr_reg_0 Q
++ FLOATING
+block1/pgm_cgm_en_reg_reg ( IN SD ) ( OUT QZ )
+block1/start_reset_dd_reg ( IN SD ) ( OUT QZ )
++ STOP block1/start_reset_d_reg SD ;
+END SCANCHAINS
+END DESIGN
From 953367f3c12c3dc82f0b155d409d044380cebfee Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 22:11:23 +0100
Subject: [PATCH 25/29] Multi-mapping for layer map files for LEF/DEF reader
---
.../lefdef/db_plugin/dbLEFDEFImporter.cc | 74 +++++++++++-------
.../lefdef/db_plugin/dbLEFDEFImporter.h | 1 -
.../lefdef/unit_tests/dbLEFDEFImportTests.cc | 18 ++++-
testdata/lefdef/multimap/.test.def.swp | Bin 12288 -> 0 bytes
4 files changed, 58 insertions(+), 35 deletions(-)
delete mode 100644 testdata/lefdef/multimap/.test.def.swp
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
index e3a90c6ee..0b3856917 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc
@@ -805,16 +805,6 @@ LEFDEFReaderState::register_layer (const std::string &ln)
++m_laynum;
}
-void
-LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, const db::LayerProperties &lp, unsigned int layer, unsigned int mask)
-{
- tl_assert (m_has_explicit_layer_mapping);
- std::set ll;
- ll.insert (layer);
- m_layers [std::make_pair (n, std::make_pair (purpose, mask))] = ll;
- m_layer_map.map (lp, layer);
-}
-
static bool try_read_layers (tl::Extractor &ex, std::vector &layers)
{
int l = 0;
@@ -861,7 +851,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
purpose_translation_rev.insert (std::make_pair (i->second, i->first));
}
- std::map >, db::LayerProperties> layer_map;
+ std::map >, std::vector > layer_map;
while (! ts.at_end ()) {
@@ -875,31 +865,37 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
} else {
std::string w1, w2;
- int layer = 0, datatype = 0;
- std::vector layers;
+ std::vector layers, datatypes;
size_t max_purpose_str = 10;
- if (! ex.try_read_word (w1) || ! ex.try_read_word (w2, "._$,/:") || ! try_read_layers (ex, layers) || ! ex.try_read (datatype)) {
+ if (! ex.try_read_word (w1) || ! ex.try_read_word (w2, "._$,/:") || ! try_read_layers (ex, layers) || ! try_read_layers (ex, datatypes)) {
tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d not understood - skipped")), path, ts.line_number ());
continue;
}
- if (layers.size () > 1) {
- tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: mapping to multiple layers not supported currently - first one taken")), path, ts.line_number ());
- }
- layer = layers.front ();
-
if (w1 == "DIEAREA") {
- layer_map [std::make_pair (std::string (), std::make_pair (Outline, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "OUTLINE");
+ for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
+ for (std::vector::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
+ layer_map [std::make_pair (std::string (), std::make_pair (Outline, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, "OUTLINE"));
+ }
+ }
} else if (w1 == "REGIONS") {
- layer_map [std::make_pair (std::string (), std::make_pair (Regions, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "REGIONS");
+ for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
+ for (std::vector::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
+ layer_map [std::make_pair (std::string (), std::make_pair (Regions, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, "REGIONS"));
+ }
+ }
} else if (w1 == "BLOCKAGE") {
- layer_map [std::make_pair (std::string (), std::make_pair (PlacementBlockage, (unsigned int) 0))] = db::LayerProperties (layer, datatype, "PLACEMENT_BLK");
+ for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
+ for (std::vector::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
+ layer_map [std::make_pair (std::string (), std::make_pair (PlacementBlockage, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, "PLACEMENT_BLK"));
+ }
+ }
} else if (w1 == "NAME") {
@@ -909,19 +905,23 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
// "(M1/LABELS): M1.LABEL"
// "(M2/LABELS): M2.LABEL"
- std::vector layers;
+ std::vector layer_names;
std::vector purposes = tl::split (w2, ",");
for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
if (*p == "DIEAREA" || *p == "ALL" || *p == "COMP") {
tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NAME record ignored for entity: %s")), path, ts.line_number (), *p);
} else {
- layers.push_back (tl::split (*p, "/").front ());
+ layer_names.push_back (tl::split (*p, "/").front ());
}
}
- std::string final_name = tl::join (layers, "/") + ".LABEL";
- for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
- layer_map [std::make_pair (*l, std::make_pair (Label, (unsigned int) 0))] = db::LayerProperties (layer, datatype, final_name);
+ std::string final_name = tl::join (layer_names, "/") + ".LABEL";
+ for (std::vector::const_iterator ln = layer_names.begin (); ln != layer_names.end (); ++ln) {
+ for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
+ for (std::vector::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
+ layer_map [std::make_pair (*ln, std::make_pair (Label, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, final_name));
+ }
+ }
}
} else if (w1 == "COMP") {
@@ -1027,7 +1027,11 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
std::string final_name = w1 + "." + purpose_str;
for (std::set >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
- layer_map [std::make_pair (w1, *p)] = db::LayerProperties (layer, datatype, final_name);
+ for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) {
+ for (std::vector::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
+ layer_map [std::make_pair (w1, *p)].push_back (db::LayerProperties (*l, *d, final_name));
+ }
+ }
}
}
@@ -1036,9 +1040,19 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
}
+ // build an explicit layer mapping now.
+
+ tl_assert (m_has_explicit_layer_mapping);
+ m_layers.clear ();
+ m_layer_map.clear ();
+
db::DirectLayerMapping lm (&layout);
- for (std::map >, db::LayerProperties>::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
- map_layer_explicit (i->first.first, i->first.second.first, i->second, lm.map_layer (i->second).second, i->first.second.second);
+ for (std::map >, std::vector >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
+ for (std::vector::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
+ unsigned int layer = lm.map_layer (*j).second;
+ m_layers [i->first].insert (layer);
+ m_layer_map.mmap (*j, layer);
+ }
}
}
diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
index f123490be..85bd52395 100644
--- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
+++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h
@@ -1202,7 +1202,6 @@ private:
std::map m_foreign_cells;
std::set open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
- void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
};
diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
index eba689a5c..f896ab0e5 100644
--- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
+++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc
@@ -710,10 +710,20 @@ TEST(117_mapfile_all)
EXPECT_EQ (lm_read.to_string (),
"layer_map("
"'OUTLINE : OUTLINE (1/0)';"
- "'M1.BLK;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/...\\' (22/2)';"
- "'\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';"
- "'\\'M1.PIN:1\\';\\'M1.SPNET:1\\';\\'M1.VIA:1\\' : \\'M1.NET:1/...\\' (6/0)';"
- "'M1.LABEL : M1.LABEL (28/1)';"
+ "'+M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/...\\' (1/5)';"
+ "'+M1.NET;M1.SPNET : \\'M1.NET/SPNET\\' (16/0)';"
+ "'+M1.NET : M1.NET (18/0)';"
+ "'+M1.BLK;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/...\\' (22/2)';"
+ "'+\\'M1.NET:1\\';\\'M1.PIN:1\\';\\'M1.SPNET:1\\';\\'M1.VIA:1\\' : \\'M1.NET:1/...\\' (6/0)';"
+ "'+\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';"
+ "'+M1.PIN : M1.PIN (3/0)';"
+ "'+M1.PIN : M1.PIN (4/0)';"
+ "'+M1.VIA : M1.VIA (20/0)';"
+ "'+M1.VIA : M1.VIA (21/0)';"
+ "'+M1.LABEL : M1.LABEL (26/0)';"
+ "'+M1.LABEL : M1.LABEL (27/0)';"
+ "'+M1.LABEL : M1.LABEL (28/1)';"
+ "'+M1.BLK : M1.BLOCKAGE (13/0)';"
"'M1_TEXT.LABEL : M1_TEXT.LABEL (29/0)'"
")"
)
diff --git a/testdata/lefdef/multimap/.test.def.swp b/testdata/lefdef/multimap/.test.def.swp
deleted file mode 100644
index 736b58e7c8210923ca3ae77b5515507a33796e9a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 12288
zcmeI2F>ljA6vwZK31~sEFfcrVgc?<;?W83|ncUd4CpC6zJE>YgmXo+m)TA|uJ9GfP
z2ooQJi3N#)g$X7Q3p<|x{^ulWg{soE=$-VpefR$N-n(DCL`h3;${MXK8Uo{%5O=q}
zg&$_0&HTJNCk9cPc6-rCh0Yt@q|lF&^e{QkgxITTLT$ev9UmU0+8`RG@lZ?SQQC>p
zNbASDop@Ip9QD)QAWE{pB3Ay9n8Qqf30#1{tSA)?T^S$b?$e#yjSK8y3lm@hOn?b6
z0Vco%m;e)C0{;tvG?@{vahNNU1Kpe4Xa2fRrhH=pOn?b60Vco%m;e)C0!)AjFaajO
z1TGwU55np8MWR*FQEfS)owvNm;e)C0!)AjFaajO1egF5U;>w%fbCdh*}hzJ
zgnIO=rc+%vrQ?eQ@&mU{t^Q$q-_S;BG)%)`Jc`q>gZm!&7FEPq(Q$a5q@z4}nkTmr
z(B=;1r}kuT5VoQCKxN9ZooQd7CmXIANM|kU#`J<|JFU?$+p5zhLUlxBAYF&rS+}A<
z?QYaNFv7|Ft@|1>268S#xa(3
z3@SasB~MLh8e!*XFgPa5B?F5(t!|S6YIdEiJ_ha6;2&Ms9v(hENPpb
zZ6YIz!>q2;0%}3e7+|F$8jcKnvZNp2jj^dFtDfs1i!xQj_?5z^&`U!6_Z};&4S!Vz
ic(**Ca!;S
Date: Sat, 19 Dec 2020 22:46:22 +0100
Subject: [PATCH 26/29] WIP: tests fixed.
---
testdata/ruby/dbLayout.rb | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/testdata/ruby/dbLayout.rb b/testdata/ruby/dbLayout.rb
index 33a1decae..c7ec7732e 100644
--- a/testdata/ruby/dbLayout.rb
+++ b/testdata/ruby/dbLayout.rb
@@ -43,7 +43,7 @@ class DBLayout_TestClass < TestBase
lmap.map( "4/2", 1 )
lmap.map( "1/2", 1 )
lmap.map( "0/0", 1 )
- assert_equal( lmap.mapping_str(1), "0/0;1/2;2-4/2" ) # could be "0/0;1-4/2" as well ...
+ assert_equal( lmap.mapping_str(1), "0/0;1-4/2" ) # could be "0/0;1-4/2" as well ...
lmap.map( RBA::LayerInfo::new(2, 2), RBA::LayerInfo::new(4, 4), 2 )
lmap.map( RBA::LayerInfo::new(0, 1), 2 )
@@ -109,31 +109,31 @@ class DBLayout_TestClass < TestBase
lmap.clear
lmap.map("*/*", 0)
lmap.mmap(RBA::LayerInfo::new(5, 10), 1)
- assert_equal(lmap.mapping_str(0), "+0-4/*;5/0-9,10,11-*;6-*/*")
+ assert_equal(lmap.mapping_str(0), "+*/*")
assert_equal(lmap.mapping_str(1), "+5/10")
lmap.clear
lmap.map("*/*", 0)
lmap.mmap(RBA::LayerInfo::new(5, 10), 1, RBA::LayerInfo::new(100, 0))
- assert_equal(lmap.mapping_str(0), "+0-4/*;5/0-9,10,11-*;6-*/*")
+ assert_equal(lmap.mapping_str(0), "+*/*")
assert_equal(lmap.mapping_str(1), "+5/10 : 100/0")
lmap.clear
lmap.map("*/*", 0)
lmap.mmap(RBA::LayerInfo::new(5, 10), RBA::LayerInfo::new(16, 21), 1)
- assert_equal(lmap.mapping_str(0), "+0-4/*;5-16/0-9,10-21,22-*;17-*/*")
+ assert_equal(lmap.mapping_str(0), "+*/*")
assert_equal(lmap.mapping_str(1), "+5-16/10-21")
lmap.clear
lmap.map("*/*", 0)
lmap.mmap(RBA::LayerInfo::new(5, 10), RBA::LayerInfo::new(16, 21), 1, RBA::LayerInfo::new(100, 0))
- assert_equal(lmap.mapping_str(0), "+0-4/*;5-16/0-9,10-21,22-*;17-*/*")
+ assert_equal(lmap.mapping_str(0), "+*/*")
assert_equal(lmap.mapping_str(1), "+5-16/10-21 : 100/0")
lmap.clear
lmap.map("*/*", 0)
lmap.mmap("5-16/10-21", 1)
- assert_equal(lmap.mapping_str(0), "+0-4/*;5-16/0-9,10-21,22-*;17-*/*")
+ assert_equal(lmap.mapping_str(0), "+*/*")
assert_equal(lmap.mapping_str(1), "+5-16/10-21")
assert_equal(lmap.logicals(RBA::LayerInfo::new(5, 10)), [ 0, 1 ])
From b6f710a9fecd09ea7c499aafda883bbca30c420c Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 19 Dec 2020 23:37:37 +0100
Subject: [PATCH 27/29] WIP: Fixed DXF reader
---
src/db/db/dbNamedLayerReader.cc | 15 ++++++++---
src/db/db/dbNamedLayerReader.h | 18 ++++++++++++-
.../streamers/dxf/db_plugin/dbDXFReader.cc | 27 +++++++------------
.../streamers/dxf/db_plugin/dbDXFReader.h | 1 -
.../{dbDXFReader.cc => dbDXFReaderTests.cc} | 0
.../streamers/dxf/unit_tests/unit_tests.pro | 2 +-
6 files changed, 39 insertions(+), 24 deletions(-)
rename src/plugins/streamers/dxf/unit_tests/{dbDXFReader.cc => dbDXFReaderTests.cc} (100%)
diff --git a/src/db/db/dbNamedLayerReader.cc b/src/db/db/dbNamedLayerReader.cc
index 9716f4cab..ca7fef294 100644
--- a/src/db/db/dbNamedLayerReader.cc
+++ b/src/db/db/dbNamedLayerReader.cc
@@ -122,25 +122,31 @@ extract_ld (const char *s, int &l, int &d, std::string &n)
std::pair
NamedLayerReader::open_layer (db::Layout &layout, const std::string &n)
+{
+ return open_layer (layout, n, keep_layer_names (), create_layers ());
+}
+
+std::pair
+NamedLayerReader::open_layer (db::Layout &layout, const std::string &n, bool keep_layer_name, bool create_layer)
{
std::map >::const_iterator lc = m_layer_cache.find (n);
if (lc != m_layer_cache.end ()) {
return lc->second;
} else {
- std::pair res = open_layer_uncached (layout, n);
+ std::pair res = open_layer_uncached (layout, n, keep_layer_name, create_layer);
m_layer_cache.insert (std::make_pair (n, res));
return res;
}
}
std::pair
-NamedLayerReader::open_layer_uncached (db::Layout &layout, const std::string &n)
+NamedLayerReader::open_layer_uncached (db::Layout &layout, const std::string &n, bool keep_layer_name, bool create_layer)
{
int l = -1, d = -1;
std::string on;
std::set li = m_layer_map.logical (n, layout);
- if (li.empty () && ! m_keep_layer_names) {
+ if (li.empty () && ! keep_layer_name) {
if (extract_plain_layer (n.c_str (), l)) {
@@ -183,7 +189,7 @@ NamedLayerReader::open_layer_uncached (db::Layout &layout, const std::string &n)
}
- } else if (! m_create_layers) {
+ } else if (! create_layer) {
return std::pair (false, 0);
@@ -212,6 +218,7 @@ NamedLayerReader::open_layer_uncached (db::Layout &layout, const std::string &n)
void
NamedLayerReader::map_layer (const std::string &name, unsigned int layer)
{
+ m_layer_cache [name] = std::make_pair (true, layer);
m_layer_map_out.map (name, layer);
}
diff --git a/src/db/db/dbNamedLayerReader.h b/src/db/db/dbNamedLayerReader.h
index 53c68d9f4..5bf234b47 100644
--- a/src/db/db/dbNamedLayerReader.h
+++ b/src/db/db/dbNamedLayerReader.h
@@ -73,6 +73,14 @@ protected:
*/
void set_layer_map (const LayerMap &lm);
+ /**
+ * @brief Gets the input layer map
+ */
+ const LayerMap &layer_map ()
+ {
+ return m_layer_map;
+ }
+
/**
* @brief Gets the layer map
*/
@@ -105,6 +113,14 @@ protected:
*/
std::pair open_layer (db::Layout &layout, const std::string &name);
+ /**
+ * @brief Opens a new layer
+ * This method will create or locate a layer for a given name.
+ * The result's first attribute is true, if such a layer could be found
+ * or created. In this case, the second attribute is the layer index.
+ */
+ std::pair open_layer (db::Layout &layout, const std::string &name, bool keep_layer_name, bool create_layer);
+
/**
* @brief Force mapping of a name to a layer index
*/
@@ -133,7 +149,7 @@ private:
std::map > m_layer_cache;
std::map, unsigned int> m_multi_mapping_placeholders;
- std::pair open_layer_uncached (db::Layout &layout, const std::string &name);
+ std::pair open_layer_uncached (db::Layout &layout, const std::string &name, bool keep_layer_name, bool create_layer);
};
}
diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
index 2335d238d..c0858a500 100644
--- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
+++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc
@@ -364,16 +364,6 @@ DXFReader::warn (const std::string &msg)
}
}
-std::pair
-DXFReader::open_layer (db::Layout &layout, const std::string &n)
-{
- if (n == zero_layer_name) {
- return std::make_pair (true, m_zero_layer);
- } else {
- return NamedLayerReader::open_layer (layout, n);
- }
-}
-
void
DXFReader::do_read (db::Layout &layout, db::cell_index_type top)
{
@@ -381,21 +371,24 @@ 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 = open_layer (layout, zero_layer_name);
- if (ll.first) {
- // layer exists
- m_zero_layer = ll.second;
+ std::pair li = NamedLayerReader::open_layer (layout, zero_layer_name, true /*keep layer name*/, false /*don't create a new layer*/);
+ if (li.first) {
+
+ // we got one from the layer mapping
+ m_zero_layer = li.second;
} else {
- // or explicitly create the layer:
- m_zero_layer = layout.insert_layer (db::LayerProperties (0, 0, zero_layer_name));
+ // or we explicitly create the layer
+ db::LayerProperties lp_zero (0, 0, zero_layer_name);
+ m_zero_layer = layout.insert_layer (lp_zero);
map_layer (zero_layer_name, m_zero_layer);
}
- // Read sections
+ // Read sections
+
int g;
while (true) {
diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h
index 54881d2cd..beed6dfcf 100644
--- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h
+++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.h
@@ -193,7 +193,6 @@ private:
void do_read (db::Layout &layout, db::cell_index_type top);
- std::pair open_layer (db::Layout &layout, const std::string &n);
db::cell_index_type make_layer_variant (db::Layout &layout, const std::string &cellname, db::cell_index_type template_cell, unsigned int layer, double sx, double sy);
void cleanup (db::Layout &layout, db::cell_index_type top);
diff --git a/src/plugins/streamers/dxf/unit_tests/dbDXFReader.cc b/src/plugins/streamers/dxf/unit_tests/dbDXFReaderTests.cc
similarity index 100%
rename from src/plugins/streamers/dxf/unit_tests/dbDXFReader.cc
rename to src/plugins/streamers/dxf/unit_tests/dbDXFReaderTests.cc
diff --git a/src/plugins/streamers/dxf/unit_tests/unit_tests.pro b/src/plugins/streamers/dxf/unit_tests/unit_tests.pro
index de728685d..98d781faa 100644
--- a/src/plugins/streamers/dxf/unit_tests/unit_tests.pro
+++ b/src/plugins/streamers/dxf/unit_tests/unit_tests.pro
@@ -6,7 +6,7 @@ TARGET = dxf_tests
include($$PWD/../../../../lib_ut.pri)
SOURCES = \
- dbDXFReader.cc \
+ dbDXFReaderTests.cc
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
From 09e088b68666ce39d05aafb849ecf8828591c8d7 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 20 Dec 2020 00:37:06 +0100
Subject: [PATCH 28/29] Added missing file.
---
testdata/gds/alm_au3.gds | Bin 0 -> 2890 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 testdata/gds/alm_au3.gds
diff --git a/testdata/gds/alm_au3.gds b/testdata/gds/alm_au3.gds
new file mode 100644
index 0000000000000000000000000000000000000000..324c893f7b7d87ff7b20f22c263fc1b937fe5319
GIT binary patch
literal 2890
zcmbW3O-NKx6vxlJ8Si^DjvuK6Mnp+Lfmvi3A&HfhVrb|jC4w&71VJJZ6+#J?1VOE=
zMFiQxT@VPhiimL4GAP1Di#CDK$|2|VKkvNLdw1}Slra8=bMOD2^X~b0LxvpZB5hAO
z?sv*lBQ;Ph)y2P)=a_SSCyAQURb40U9qs?{a`jlx(t&4BMhmpPDp{8^rZ9A3V3;W5
z5t$l?QehandO3iBcV`kEnJUP10j;3pC3@
ze*rA9f1%ow{j-k!3sW7e!zZNLZU5;X@#kNkg8x0fzdi-s7b54rQteDDe&>JnS-Jmo
zs5iSf3tn9s|BKXA&m`afy}~3)@3g!c%j;W2br(^;MYK0@W4o1VXC~=!_}5?^WF4Nm
zN2&Hm?^4D3@{H*l7&%0l98s=8Yb_tt*45xag4)@5HMc4;TB~MTYMKZqAf|^2CzS2c
zb2h5*;w+Kt`98DuGf~y`h-!De_+8l*^6z@m3+2NQtiyR|F|A^
z&={6>sC-L#o}(TY5M0k4n3P=X)dcUn7UN@I9p3OK&Ra
zq3LHmVn5CLh-#<)%KGf0=yNYbuT*<>v9i9pQ}p>GqF1WDx>NM|zw>%4zcn$Dq;62B
zrWsSu+J!3BU4N_DYc_)y3P=#YJvW)7cux=Y4V)dsPE13uL8dBvB1ZYsIclxt&IgMd
zt~EVNUfZ#nytc19d9B@^$W|=JSCVzT2b0%^rjyskK1FL75B&SZng`|6srX)|6SI6e
zg?g(W*Ltz98~p&f@HL9JgHr9L+p4FSo@jh8>xHbFSQ0%`?PYqapVl5>-yHmd?hN|z
zK}5BiIm>@cPjsoB^+Io(N4;8#-q5uE@
literal 0
HcmV?d00001
From 5a828b4c8f10ae802b255b27d2b8b60c1fa16dfc Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 20 Dec 2020 17:57:34 +0100
Subject: [PATCH 29/29] WIP: code cleanup
---
src/db/db/dbCommonReader.cc | 9 ---------
src/db/db/dbNamedLayerReader.cc | 9 ---------
2 files changed, 18 deletions(-)
diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc
index a64de5f72..f52e5cdf2 100644
--- a/src/db/db/dbCommonReader.cc
+++ b/src/db/db/dbCommonReader.cc
@@ -313,15 +313,6 @@ CommonReader::init (const LoadLayoutOptions &options)
m_layer_cache.clear ();
m_layers_created.clear ();
m_layer_names.clear ();
-
- // create a pseudo-multimapping for single targets
- for (db::LayerMap::const_iterator_layers li = m_common_options.layer_map.begin (); li != m_common_options.layer_map.end (); ++li) {
- for (db::LayerMap::const_iterator_datatypes di = li->second.begin (); di != li->second.end (); ++di) {
- if (di->second.size () == 1) {
- m_multi_mapping_placeholders.insert (std::make_pair (di->second, *di->second.begin ()));
- }
- }
- }
}
void
diff --git a/src/db/db/dbNamedLayerReader.cc b/src/db/db/dbNamedLayerReader.cc
index ca7fef294..c9fce8438 100644
--- a/src/db/db/dbNamedLayerReader.cc
+++ b/src/db/db/dbNamedLayerReader.cc
@@ -233,15 +233,6 @@ NamedLayerReader::prepare_layers (db::Layout &layout)
m_layer_cache.clear ();
m_layer_map.prepare (layout);
-
- // create a pseudo-multimapping for single targets
- for (db::LayerMap::const_iterator_layers li = m_layer_map.begin (); li != m_layer_map.end (); ++li) {
- for (db::LayerMap::const_iterator_datatypes di = li->second.begin (); di != li->second.end (); ++di) {
- if (di->second.size () == 1) {
- m_multi_mapping_placeholders.insert (std::make_pair (di->second, *di->second.begin ()));
- }
- }
- }
}
void