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 #include +#include namespace db { @@ -161,6 +162,15 @@ struct DB_PUBLIC LDPair * and effectively rename a layer or add layer name information to * a GDS layer/datatype layer. * + * "Unmapping" can be used to create "holes" in ranges of layers. + * For example, by first mapping layers 1 to 100, datatype 0 and then + * unmapping layer 50, datatype 0, the layers 1 to 49 and 51 to 100, datatype 0 + * are mapped. + * + * The layer map supports multi-mapping. That is, one input layer is + * mapped to multiple target layers. It also supports merging but + * mapping different input layers to a single target layer. + * * A layer map object can be used as a standalone object or in * conjunction with a layout object. As a standalone object, the * logical layers (indexes) are simply consecutive numbers. @@ -178,11 +188,11 @@ class DB_PUBLIC LayerMap : public gsi::ObjectBase { public: - typedef tl::interval_map datatype_map; + typedef tl::interval_map > datatype_map; typedef tl::interval_map ld_map; typedef ld_map::const_iterator const_iterator_layers; typedef datatype_map::const_iterator const_iterator_datatypes; - typedef std::map::const_iterator const_iterator_names; + typedef std::map >::const_iterator const_iterator_names; /** * @brief The constructor for an empty map @@ -195,7 +205,7 @@ public: * @return A pair telling if the layer is mapped (first=true) and * the logical layer mapped (second) if this is the case. */ - std::pair logical (const LDPair &p) const; + std::set logical (const LDPair &p) const; /** * @brief Query a layer mapping from a name @@ -203,7 +213,7 @@ public: * @return A pair telling if the layer is mapped (first=true) and * the logical layer mapped (second) if this is the case. */ - std::pair logical (const std::string &name) const; + std::set logical (const std::string &name) const; /** * @brief Query a layer mapping from a name or LDPair @@ -213,7 +223,7 @@ public: * * @param p The layer that is looked for */ - std::pair logical (const db::LayerProperties &p) const; + std::set logical (const db::LayerProperties &p) const; /** * @brief Query or install a layer mapping from a name or LDPair @@ -227,14 +237,14 @@ public: * the logical layers are placeholder values which will be replaced by * true layers during this method if a new layer is requested. */ - std::pair logical (const db::LayerProperties &p, db::Layout &layout) const; + std::set logical (const db::LayerProperties &p, db::Layout &layout) const; /** * @brief Query or install a layer mapping from a LDPair * * See the version for LayerProperties about details. */ - std::pair logical (const db::LDPair &p, db::Layout &layout) const; + std::set logical (const db::LDPair &p, db::Layout &layout) const; /** * @brief Gets the target layer for a given logical layer @@ -371,6 +381,39 @@ public: */ void map_expr (tl::Extractor &ex, unsigned int l); + /** + * @brief Unmaps a LDPair + */ + void unmap (const LDPair &f); + + /** + * @brief Unmaps the layer with the given name + */ + void unmap (const std::string &name); + + /** + * @brief Unmaps a layer with the given layer properties + */ + void unmap (const LayerProperties &f); + + /** + * @brief Removes any mapping for a range of ldpair's + * + * The range is given by two pairs p1,p2. The layers + * between [p1.l,p2.l] and with datatypes between [p1.d,p2.d] are unmapped. + */ + void unmap (const LDPair &p1, const LDPair &p2); + + /** + * @brief Removes any mapping for the layers given by the expression + */ + void unmap_expr (const std::string &expr); + + /** + * @brief Removes any mapping for the layers given by the expression + */ + void unmap_expr (tl::Extractor &ex); + /** * @brief Prepares a layer mapping object for reading * @@ -454,7 +497,7 @@ public: private: ld_map m_ld_map; - std::map m_name_map; + std::map > m_name_map; std::map m_target_layers; std::vector m_placeholders; unsigned int m_next_index; @@ -462,12 +505,12 @@ private: void insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties *t); void insert (const std::string &name, unsigned int l, const LayerProperties *t); - std::pair logical_internal (const LDPair &p, bool allow_placeholder) const; - std::pair logical_internal (const std::string &name, bool allow_placeholder) const; - std::pair logical_internal (const db::LayerProperties &p, bool allow_placeholder) const; + std::set logical_internal (const LDPair &p, bool allow_placeholder) const; + std::set logical_internal (const std::string &name, bool allow_placeholder) const; + std::set logical_internal (const db::LayerProperties &p, bool allow_placeholder) const; - std::pair substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout); - bool is_placeholder (unsigned int l) const; + std::set substitute_placeholder (const db::LayerProperties &p, const std::set &ph, db::Layout &layout); + bool is_placeholder (const std::set &l) const; }; } From 7852568284cf477fd06e64577b34d061fa69ec6e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 15 Dec 2020 18:42:43 +0100 Subject: [PATCH 10/29] WIP --- src/db/db/gsiDeclDbReader.cc | 98 +++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/src/db/db/gsiDeclDbReader.cc b/src/db/db/gsiDeclDbReader.cc index 24b4e5b2e..16ab5bf71 100644 --- a/src/db/db/gsiDeclDbReader.cc +++ b/src/db/db/gsiDeclDbReader.cc @@ -36,17 +36,23 @@ namespace gsi static bool lm_is_mapped (const db::LayerMap *layer_map, const db::LayerProperties &lp) { - return layer_map->logical (lp).first; + return !layer_map->logical (lp).empty (); } static int lm_logical (const db::LayerMap *layer_map, const db::LayerProperties &lp) { - std::pair lm = layer_map->logical (lp); - return lm.first ? int (lm.second) : -1; + std::set lm = layer_map->logical (lp); + return lm.empty () ? -1 : int (*lm.begin ()); } - static db::LayerProperties + static std::set + lm_logicals (const db::LayerMap *layer_map, const db::LayerProperties &lp) + { + return layer_map->logical (lp); + } + + static db::LayerProperties lm_mapping (const db::LayerMap *layer_map, unsigned int l) { return layer_map->mapping (l); @@ -82,16 +88,44 @@ namespace gsi layer_map->map_expr (s, l); } + static void + lm_unmap (db::LayerMap *layer_map, const db::LayerProperties &lp) + { + layer_map->unmap (lp); + } + + static void + lm_unmap_interval (db::LayerMap *layer_map, const db::LayerProperties &lp1, const db::LayerProperties &lp2) + { + layer_map->unmap (ldpair_from_lp (lp1), ldpair_from_lp (lp2)); + } + + static void + lm_unmap_string (db::LayerMap *layer_map, std::string &s) + { + layer_map->unmap_expr (s); + } + Class decl_LayerMap ("db", "LayerMap", gsi::method_ext ("is_mapped?", &lm_is_mapped, gsi::arg ("layer"), "@brief Check, if a given physical layer is mapped\n" "@param layer The physical layer specified with an \\LayerInfo object.\n" "@return True, if the layer is mapped." ) + - gsi::method_ext ("logical", &lm_logical, gsi::arg ("layer"), + gsi::method_ext ("#logical", &lm_logical, gsi::arg ("layer"), "@brief Returns the logical layer (the layer index in the layout object) for a given physical layer.n" "@param layer The physical layer specified with an \\LayerInfo object.\n" "@return The logical layer index or -1 if the layer is not mapped." + "\n" + "This method is deprecated with version 0.27 as in this version, layers can be mapped to multiple targets which " + "this method can't capture. Use \\logicals instead.\n" + ) + + gsi::method_ext ("logicals", &lm_logicals, gsi::arg ("layer"), + "@brief Returns the logical layers for a given physical layer.n" + "@param layer The physical layer specified with an \\LayerInfo object.\n" + "@return This list of logical layers this physical layer as mapped to or empty if there is no mapping." + "\n" + "This method has been introduced in version 0.27.\n" ) + gsi::method ("mapping_str", &db::LayerMap::mapping_str, gsi::arg ("log_layer"), "@brief Returns the mapping string for a given logical layer\n" @@ -162,11 +196,39 @@ namespace gsi "separated by a hyphen. Examples are: \"1/2\", \"1-5/0\", \"1,2,5/0\",\n" "\"1/5;5/6\".\n" "\n" - "A target layer can be specified with the \":\" notation where " - "the target is a valid layer specification string (i.e. \"1/0\").\n" + "layer/datatype wildcards can be specified with \"*\". When \"*\" is used\n" + "for the upper limit, it is equivalent to \"all layer above\". When used\n" + "alone, it is equivalent to \"all layers\". Examples: \"1 / *\", \"* / 10-*\"\n" + "\n" + "Named layers are specified simply by specifying the name, if\n" + "necessary in single or double quotes (if the name begins with a digit or\n" + "contains non-word characters). layer/datatype and name descriptions can\n" + "be mixed, i.e. \"AA;1/5\" (meaning: name \"AA\" or layer 1/datatype 5).\n" + "\n" + "A target layer can be specified with the \":\" notation, where\n" + "target is a valid string for a LayerProperties() object.\n" + "\n" + "A target can include relative layer/datatype specifications and wildcards.\n" + "For example, \"1-10/0: *+1/0\" will add 1 to the original layer number.\n" + "\"1-10/0-50: * / *\" will use the original layers.\n" "\n" "Target mapping has been added in version 0.20.\n" ) + + gsi::method_ext ("unmap", &lm_unmap, gsi::arg ("phys_layer"), + "@brief Unmaps the given layer\n" + "Unmapping will remove the specific layer from the mapping. This method allows generating " + "'mapping holes' by first mapping a range and then unmapping parts of it.\n" + "\n" + "This method has been introduced in version 0.27." + ) + + gsi::method_ext ("unmap", &lm_unmap_interval, gsi::arg ("pl_start"), gsi::arg ("pl_stop"), + "@brief Unmaps the layers from the given interval\n" + "This method has been introduced in version 0.27." + ) + + gsi::method_ext ("unmap", &lm_unmap_string, gsi::arg ("expr"), + "@brief Unmaps the layers from the given expression\n" + "This method has been introduced in version 0.27." + ) + gsi::method ("clear", &db::LayerMap::clear, "@brief Clears the map\n" ) + @@ -221,7 +283,27 @@ namespace gsi "ly.read(\"input.gds\", lo)\n" "@/code\n" "\n" - "The LayerMap class has been introduced in version 0.18." + "1:n mapping is possible: a physical layer can be mapped to multiple logical layers. For this, mapping acts additive. " + "The following example will map layer 1, datatypes 0 to 255 to logical layer 0, and layer 1, datatype 17 to logical layers " + "0 plus 1:" + "\n" + "@code" + "lm = RBA::LayerMap::new\n" + "lm.map(\"1/0-255\", 0)\n" + "lm.map(\"1/17\", 1)\n" + "@/code\n" + "\n" + "'unmapping' allows to remove a mapping. This allows creating 'holes' in mapping ranges. The followin example maps " + "layer 1, datatypes 0 to 16 and 18 to 255 to logical layer 0:" + "\n" + "@code" + "lm = RBA::LayerMap::new\n" + "lm.map(\"1/0-255\", 0)\n" + "lm.unmap(\"1/17\")\n" + "@/code\n" + "\n" + "The LayerMap class has been introduced in version 0.18. Target layer have been introduced in version 0.20. " + "1:n mapping and unmapping has been introduced in version 0.27." ); // NOTE: the contribution comes from format specific extensions. From 1f635015ce65b143741bde51e2c1b3ae3ef632cc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 15 Dec 2020 23:05:34 +0100 Subject: [PATCH 11/29] WIP: backward compatible implementation of multi-map capability of layer mapping. --- src/db/db/dbGlyphs.cc | 12 +- src/db/db/dbLayoutQuery.cc | 2 +- src/db/db/dbNamedLayerReader.cc | 6 +- src/db/db/dbStreamLayers.cc | 84 ++++++++-- src/db/db/dbStreamLayers.h | 145 +++++++++++++++--- src/db/db/gsiDeclDbReader.cc | 86 ++++++++++- src/db/unit_tests/dbStreamLayerTests.cc | 126 +++++++++++---- src/lay/lay/laySearchReplaceDialog.cc | 2 +- .../streamers/dxf/db_plugin/dbDXFReader.cc | 2 +- .../gds2/db_plugin/dbGDS2ReaderBase.cc | 2 +- .../streamers/gds2/unit_tests/dbGDS2Reader.cc | 2 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 6 +- .../oasis/db_plugin/dbOASISReader.cc | 2 +- 13 files changed, 393 insertions(+), 84 deletions(-) diff --git a/src/db/db/dbGlyphs.cc b/src/db/db/dbGlyphs.cc index ecea36e12..9cefc8b5e 100644 --- a/src/db/db/dbGlyphs.cc +++ b/src/db/db/dbGlyphs.cc @@ -174,9 +174,9 @@ TextGenerator::load_from_data (const char *data, size_t ndata, const std::string m_description = description; m_name = name; - std::pair l1 = map.logical (db::LDPair (1, 0)); - std::pair l2 = map.logical (db::LDPair (2, 0)); - std::pair l3 = map.logical (db::LDPair (3, 0)); + std::pair l1 = map.first_logical (db::LDPair (1, 0)); + std::pair l2 = map.first_logical (db::LDPair (2, 0)); + std::pair l3 = map.first_logical (db::LDPair (3, 0)); if (l1.first && l2.first) { read_from_layout (layout, l1.second, l2.second, l3.second); @@ -193,9 +193,9 @@ TextGenerator::load_from_file (const std::string &filename) m_description = filename; - std::pair l1 = map.logical (db::LDPair (1, 0)); - std::pair l2 = map.logical (db::LDPair (2, 0)); - std::pair l3 = map.logical (db::LDPair (3, 0)); + std::pair l1 = map.first_logical (db::LDPair (1, 0)); + std::pair l2 = map.first_logical (db::LDPair (2, 0)); + std::pair l3 = map.first_logical (db::LDPair (3, 0)); if (l1.first && l2.first) { read_from_layout (layout, l1.second, l2.second, l3.second); diff --git a/src/db/db/dbLayoutQuery.cc b/src/db/db/dbLayoutQuery.cc index 27ed3d8ad..3cf34a18e 100644 --- a/src/db/db/dbLayoutQuery.cc +++ b/src/db/db/dbLayoutQuery.cc @@ -228,7 +228,7 @@ public: { // get the layers which we have to look for for (db::Layout::layer_iterator l = layout->begin_layers (); l != layout->end_layers (); ++l) { - if (layers.is_empty () || layers.logical (*(*l).second).first) { + if (layers.is_empty () || layers.is_mapped (*(*l).second)) { m_layers.push_back ((*l).first); } } diff --git a/src/db/db/dbNamedLayerReader.cc b/src/db/db/dbNamedLayerReader.cc index 497fad153..adff2797f 100644 --- a/src/db/db/dbNamedLayerReader.cc +++ b/src/db/db/dbNamedLayerReader.cc @@ -128,7 +128,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n) std::pair ll (false, 0); - ll = m_layer_map.logical (n, layout); + ll = m_layer_map.first_logical (n, layout); if (! ll.first && !m_keep_layer_names) { if (extract_plain_layer (n.c_str (), l)) { @@ -136,7 +136,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n) db::LayerProperties lp; lp.layer = l; lp.datatype = 0; - ll = m_layer_map.logical (lp, layout); + ll = m_layer_map.first_logical (lp, layout); } else if (extract_ld (n.c_str (), l, d, on)) { @@ -144,7 +144,7 @@ NamedLayerReader::open_layer (db::Layout &layout, const std::string &n) lp.layer = l; lp.datatype = d; lp.name = on; - ll = m_layer_map.logical (lp, layout); + ll = m_layer_map.first_logical (lp, layout); } diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc index f73d3dc11..e507ddea9 100644 --- a/src/db/db/dbStreamLayers.cc +++ b/src/db/db/dbStreamLayers.cc @@ -67,7 +67,7 @@ struct LmapEraseDatatypeInterval 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); + a.erase (m_dfrom, m_dto + 1); } else { a.clear (); } @@ -90,6 +90,40 @@ LayerMap::LayerMap () // .. nothing yet .. } +bool +LayerMap::is_mapped (const LDPair &p) const +{ + const datatype_map *dm = m_ld_map.mapped (p.layer); + if (!dm) { + return false; + } + const std::set *l = dm->mapped (p.datatype); + return (l && ! l->empty ()); +} + +bool +LayerMap::is_mapped (const std::string &n) const +{ + std::map >::const_iterator m = m_name_map.find (n); + return m != m_name_map.end () && ! m->second.empty (); +} + +bool +LayerMap::is_mapped (const db::LayerProperties &p) const +{ + std::set m; + if (p.layer >= 0 && p.datatype >= 0) { + if (is_mapped (db::LDPair (p.layer, p.datatype))) { + return true; + } + } + if (! p.name.empty ()) { + return is_mapped (p.name); + } else { + return false; + } +} + std::set LayerMap::logical (const LDPair &p) const { @@ -233,13 +267,19 @@ LayerMap::mapping_str (unsigned int ll) const { std::string s; bool f1 = true; + bool is_mmap = false; for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) { bool f2 = true; for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) { + if (d->second.find (ll) != d->second.end ()) { + if (d->second.size () > 1) { + is_mmap = true; + } + // create a string representation if (!f2) { s += ","; @@ -268,6 +308,10 @@ LayerMap::mapping_str (unsigned int ll) const if (l->second.find (ll) != l->second.end ()) { + if (l->second.size () > 1) { + is_mmap = true; + } + if (!f1) { s += ";"; } @@ -285,7 +329,11 @@ LayerMap::mapping_str (unsigned int ll) const s += t->second.to_string (true); } - return s; + if (is_mmap) { + return "+" + s; + } else { + return s; + } } void @@ -439,19 +487,19 @@ LayerMap::mapping (unsigned int ll) const } void -LayerMap::map (const LDPair &p, unsigned int l) +LayerMap::mmap (const LDPair &p, unsigned int l) { insert (p, p, l, (const LayerProperties *) 0); } void -LayerMap::map (const std::string &name, unsigned int l) +LayerMap::mmap (const std::string &name, unsigned int l) { insert (name, l, (const LayerProperties *) 0); } void -LayerMap::map (const LayerProperties &f, unsigned int l) +LayerMap::mmap (const LayerProperties &f, unsigned int l) { if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) { map (db::LDPair (f.layer, f.datatype), l); @@ -462,19 +510,19 @@ LayerMap::map (const LayerProperties &f, unsigned int l) } void -LayerMap::map (const LDPair &p, unsigned int l, const LayerProperties &t) +LayerMap::mmap (const LDPair &p, unsigned int l, const LayerProperties &t) { insert (p, p, l, &t); } void -LayerMap::map (const std::string &name, unsigned int l, const LayerProperties &t) +LayerMap::mmap (const std::string &name, unsigned int l, const LayerProperties &t) { insert (name, l, &t); } void -LayerMap::map (const LayerProperties &f, unsigned int l, const LayerProperties &t) +LayerMap::mmap (const LayerProperties &f, unsigned int l, const LayerProperties &t) { if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) { map (db::LDPair (f.layer, f.datatype), l, t); @@ -485,13 +533,13 @@ LayerMap::map (const LayerProperties &f, unsigned int l, const LayerProperties & } void -LayerMap::map (const LDPair &p1, const LDPair &p2, unsigned int l) +LayerMap::mmap (const LDPair &p1, const LDPair &p2, unsigned int l) { insert (p1, p2, l, (const LayerProperties *) 0); } void -LayerMap::map (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &lp) +LayerMap::mmap (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &lp) { insert (p1, p2, l, &lp); } @@ -537,15 +585,15 @@ parse_intervals (tl::Extractor &ex, ld_interval_vector &v) } void -LayerMap::map_expr (const std::string &expr, unsigned int l) +LayerMap::mmap_expr (const std::string &expr, unsigned int l) { tl::Extractor ex (expr.c_str ()); - map_expr (ex, l); + mmap_expr (ex, l); ex.expect_end (); } void -LayerMap::map_expr (tl::Extractor &ex, unsigned int l) +LayerMap::mmap_expr (tl::Extractor &ex, unsigned int l) { try { @@ -684,7 +732,7 @@ LayerMap::unmap (const LDPair &p1, const LDPair &p2) 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); + m_ld_map.add (p1.layer, p2.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); } @@ -812,7 +860,13 @@ LayerMap::from_string_file_format (const std::string &s) } else { if (! ex.at_end ()) { - lm.map_expr (ex, l); + if (ex.test ("+")) { + lm.mmap_expr (ex, l); + } else if (ex.test ("-")) { + lm.unmap_expr (ex); + } else { + lm.map_expr (ex, l); + } if (ex.test ("#") || ex.test ("//")) { // ignore comments } else { diff --git a/src/db/db/dbStreamLayers.h b/src/db/db/dbStreamLayers.h index 8ea0d78b5..26c15804a 100644 --- a/src/db/db/dbStreamLayers.h +++ b/src/db/db/dbStreamLayers.h @@ -199,7 +199,35 @@ public: */ LayerMap (); - /** + /** + * @brief Returns the first logical layer for a given layer specification + */ + template + std::pair first_logical (const L &p) const + { + std::set r = logical (p); + if (r.empty ()) { + return std::make_pair (false, 0); + } else { + return std::make_pair (true, *r.begin ()); + } + } + + /** + * @brief Returns the first logical layer for a given layer specification + */ + template + std::pair first_logical (const L &p, db::Layout &layout) const + { + std::set r = logical (p, layout); + if (r.empty ()) { + return std::make_pair (false, 0); + } else { + return std::make_pair (true, *r.begin ()); + } + } + + /** * @brief Query a layer mapping * * @return A pair telling if the layer is mapped (first=true) and @@ -246,6 +274,21 @@ public: */ std::set logical (const db::LDPair &p, db::Layout &layout) const; + /** + * @brief Returns a value indicating whether a layer (given by layer/datatype) is mapped + */ + bool is_mapped (const LDPair &p) const; + + /** + * @brief Returns a value indicating whether the given named layer is mapped + */ + bool is_mapped (const std::string &name) const; + + /** + * @brief Returns a value indicating whether a layer is mapped + */ + bool is_mapped (const db::LayerProperties &p) const; + /** * @brief Gets the target layer for a given logical layer * @@ -280,17 +323,81 @@ public: std::vector get_layers () const; /** - * @brief Map a ldpair to a logical layer + * @brief Single-map a physical to a logical layer + * + * "Single-mapping" substitutes a layer mapping. "Multimapping" (mmap_..) + * adds to a given mapping and allows generating 1:n mappings (m:n in fact). */ - void map (const LDPair &p, unsigned int l); + template + void map (const S &p, unsigned int l) + { + unmap (p); + mmap (p, l); + } /** - * @brief Map a name to a logical layer + * @brief Single-map a physical to a logical layer with a target layer */ - void map (const std::string &name, unsigned int l); + template + void map (const S &p, unsigned int l, const LayerProperties &t) + { + unmap (p); + mmap (p, l, t); + } /** - * @brief Map a name or LDPair to a logical layer + * @brief Single-map a physical layer interval with a target layer + */ + void map (const LDPair &p1, const LDPair &p2, unsigned int l) + { + unmap (p1, p2); + mmap (p1, p2, l); + } + + /** + * @brief Single-map a physical layer interval with a target layer + */ + void map (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &t) + { + unmap (p1, p2); + mmap (p1, p2, l, t); + } + + /** + * @brief Single-map a physical layer interval (given by an expression) + */ + void map_expr (const std::string &expr, unsigned int l) + { + unmap_expr (expr); + mmap_expr (expr, l); + } + + /** + * @brief Same a map_expr with a string argument but taking the expression for a tl::Extractor + */ + void map_expr (tl::Extractor &ex, unsigned int l) + { + tl::Extractor ex1 = ex; + unmap_expr (ex1); + mmap_expr (ex, l); + } + + /** + * @brief Multi-map a ldpair to a logical layer + * + * "Multimapping" will not substitute but add to the mapping. + */ + void mmap (const LDPair &p, unsigned int l); + + /** + * @brief Multi-map a name to a logical layer + * + * "Multimapping" will not substitute but add to the mapping. + */ + void mmap (const std::string &name, unsigned int l); + + /** + * @brief Multi-map a name or LDPair to a logical layer * * The algorithm chooses the LDPair from the LayerProperties structure and/or * the name if no LDPair is given. If the source LayerProperties structure does @@ -299,26 +406,26 @@ public: * @param f The source (where to derive the match expression from) * @param l The logical layer to map to the match expression */ - void map (const LayerProperties &f, unsigned int l); + void mmap (const LayerProperties &f, unsigned int l); /** - * @brief Map a ldpair to a logical layer with a target layer + * @brief Multi-map a ldpair to a logical layer with a target layer * * The target layer specifies which layer to create for the * corresponding input. */ - void map (const LDPair &p, unsigned int l, const LayerProperties &t); + void mmap (const LDPair &p, unsigned int l, const LayerProperties &t); /** - * @brief Map a name to a logical layer with a target layer + * @brief Multi-map a name to a logical layer with a target layer * * The target layer specifies which layer to create for the * corresponding input. */ - void map (const std::string &name, unsigned int l, const LayerProperties &t); + void mmap (const std::string &name, unsigned int l, const LayerProperties &t); /** - * @brief Map a name or LDPair to a logical layer with a target layer + * @brief Multi-map a name or LDPair to a logical layer with a target layer * * The algorithm chooses the LDPair from the LayerProperties structure or * the name if no LDPair is given. If the source LayerProperties structure does @@ -328,23 +435,23 @@ public: * @param l The logical layer to map to the match expression * @param t The target layer to use for the mapped layer */ - void map (const LayerProperties &f, unsigned int l, const LayerProperties &t); + void mmap (const LayerProperties &f, unsigned int l, const LayerProperties &t); /** - * @brief Map a range of ldpair's to a logical layer + * @brief Multi-map a range of ldpair's to a logical layer * * The range is given by two pairs p1,p2. The layers * mapped are [p1.l,p2.l], the datatypes mapped are [p1.d,p2.d]. */ - void map (const LDPair &p1, const LDPair &p2, unsigned int l); + void mmap (const LDPair &p1, const LDPair &p2, unsigned int l); /** - * @brief Map a range of ldpair's to a logical layer with a target layer + * @brief Multi-map a range of ldpair's to a logical layer with a target layer * * The range is given by two pairs p1,p2. The layers * mapped are [p1.l,p2.l], the datatypes mapped are [p1.d,p2.d]. */ - void map (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &t); + void mmap (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &t); /** * @brief Map a range given by a string expression to a logical layer @@ -374,12 +481,12 @@ public: * This method will throw a LayerSpecFormatException if * something is wrong with the format string */ - void map_expr (const std::string &expr, unsigned int l); + void mmap_expr (const std::string &expr, unsigned int l); /** * @brief Same a map_expr with a string argument but taking the expression for a tl::Extractor */ - void map_expr (tl::Extractor &ex, unsigned int l); + void mmap_expr (tl::Extractor &ex, unsigned int l); /** * @brief Unmaps a LDPair diff --git a/src/db/db/gsiDeclDbReader.cc b/src/db/db/gsiDeclDbReader.cc index 16ab5bf71..19b82c6d3 100644 --- a/src/db/db/gsiDeclDbReader.cc +++ b/src/db/db/gsiDeclDbReader.cc @@ -36,7 +36,7 @@ namespace gsi static bool lm_is_mapped (const db::LayerMap *layer_map, const db::LayerProperties &lp) { - return !layer_map->logical (lp).empty (); + return layer_map->is_mapped (lp); } static int @@ -88,6 +88,36 @@ namespace gsi layer_map->map_expr (s, l); } + static void + lm_mmap (db::LayerMap *layer_map, const db::LayerProperties &lp, unsigned int l) + { + layer_map->mmap (lp, l); + } + + static void + lm_mmap_with_target (db::LayerMap *layer_map, const db::LayerProperties &lp, unsigned int l, const db::LayerProperties &t) + { + layer_map->mmap (lp, l, t); + } + + static void + lm_mmap_interval (db::LayerMap *layer_map, const db::LayerProperties &lp1, const db::LayerProperties &lp2, unsigned int l) + { + layer_map->mmap (ldpair_from_lp (lp1), ldpair_from_lp (lp2), l); + } + + static void + lm_mmap_interval_with_target (db::LayerMap *layer_map, const db::LayerProperties &lp1, const db::LayerProperties &lp2, unsigned int l, const db::LayerProperties &t) + { + layer_map->mmap (ldpair_from_lp (lp1), ldpair_from_lp (lp2), l, t); + } + + static void + lm_mmap_string (db::LayerMap *layer_map, std::string &s, unsigned int l) + { + layer_map->mmap_expr (s, l); + } + static void lm_unmap (db::LayerMap *layer_map, const db::LayerProperties &lp) { @@ -214,6 +244,51 @@ namespace gsi "\n" "Target mapping has been added in version 0.20.\n" ) + + gsi::method_ext ("mmap", &lm_mmap, gsi::arg ("phys_layer"), gsi::arg ("log_layer"), + "@brief Maps a physical layer to a logical one and adds to existing mappings\n" + "\n" + "This method acts like the corresponding 'map' method, but adds the logical layer to the receivers of the " + "given physical one. Hence this method implements 1:n mapping capabilities.\n" + "For backward compatibility, 'map' still substitutes mapping.\n" + "\n" + "Multi-mapping has been added in version 0.27.\n" + ) + + gsi::method_ext ("mmap", &lm_mmap_with_target, gsi::arg ("phys_layer"), gsi::arg ("log_layer"), gsi::arg ("target_layer"), + "@brief Maps a physical layer to a logical one, adds to existing mappings and specifies a target layer\n" + "\n" + "This method acts like the corresponding 'map' method, but adds the logical layer to the receivers of the " + "given physical one. Hence this method implements 1:n mapping capabilities.\n" + "For backward compatibility, 'map' still substitutes mapping.\n" + "\n" + "Multi-mapping has been added in version 0.27.\n" + ) + + gsi::method_ext ("mmap", &lm_mmap_interval, gsi::arg ("pl_start"), gsi::arg ("pl_stop"), gsi::arg ("log_layer"), + "@brief Maps a physical layer from the given interval to a logical one and adds to existing mappings\n" + "\n" + "This method acts like the corresponding 'map' method, but adds the logical layer to the receivers of the " + "given physical one. Hence this method implements 1:n mapping capabilities.\n" + "For backward compatibility, 'map' still substitutes mapping.\n" + "\n" + "Multi-mapping has been added in version 0.27.\n" + ) + + gsi::method_ext ("mmap", &lm_mmap_interval_with_target, gsi::arg ("pl_start"), gsi::arg ("pl_stop"), gsi::arg ("log_layer"), gsi::arg ("layer_properties"), + "@brief Maps a physical layer from the given interval to a logical one, adds to existing mappings and specifies a target layer\n" + "\n" + "This method acts like the corresponding 'map' method, but adds the logical layer to the receivers of the " + "given physical one. Hence this method implements 1:n mapping capabilities.\n" + "For backward compatibility, 'map' still substitutes mapping.\n" + "\n" + "Multi-mapping has been added in version 0.27.\n" + ) + + gsi::method_ext ("mmap", &lm_mmap_string, gsi::arg ("map_expr"), gsi::arg ("log_layer"), + "@brief Maps a physical layer given by an expression to a logical one and adds to existing mappings\n" + "\n" + "This method acts like the corresponding 'map' method, but adds the logical layer to the receivers of the " + "given physical one. Hence this method implements 1:n mapping capabilities.\n" + "For backward compatibility, 'map' still substitutes mapping.\n" + "\n" + "Multi-mapping has been added in version 0.27.\n" + ) + gsi::method_ext ("unmap", &lm_unmap, gsi::arg ("phys_layer"), "@brief Unmaps the given layer\n" "Unmapping will remove the specific layer from the mapping. This method allows generating " @@ -283,17 +358,18 @@ namespace gsi "ly.read(\"input.gds\", lo)\n" "@/code\n" "\n" - "1:n mapping is possible: a physical layer can be mapped to multiple logical layers. For this, mapping acts additive. " + "1:n mapping is supported: a physical layer can be mapped to multiple logical layers using 'mmap' instead of 'map'. When using this variant, " + "mapping acts additive.\n" "The following example will map layer 1, datatypes 0 to 255 to logical layer 0, and layer 1, datatype 17 to logical layers " "0 plus 1:" "\n" "@code" "lm = RBA::LayerMap::new\n" - "lm.map(\"1/0-255\", 0)\n" - "lm.map(\"1/17\", 1)\n" + "lm.map(\"1/0-255\", 0) # (can be 'mmap' too)\n" + "lm.mmap(\"1/17\", 1)\n" "@/code\n" "\n" - "'unmapping' allows to remove a mapping. This allows creating 'holes' in mapping ranges. The followin example maps " + "'unmapping' allows removing a mapping. This allows creating 'holes' in mapping ranges. The followin example maps " "layer 1, datatypes 0 to 16 and 18 to 255 to logical layer 0:" "\n" "@code" diff --git a/src/db/unit_tests/dbStreamLayerTests.cc b/src/db/unit_tests/dbStreamLayerTests.cc index b0ccf4f10..353e31693 100644 --- a/src/db/unit_tests/dbStreamLayerTests.cc +++ b/src/db/unit_tests/dbStreamLayerTests.cc @@ -29,14 +29,14 @@ TEST(1) db::LayerMap lm; lm.map (db::LDPair (1, 5), 17); - EXPECT_EQ (lm.logical (db::LDPair (1, 6)).first, false); - EXPECT_EQ (lm.logical (db::LDPair (1, 5)).first, true); - EXPECT_EQ (lm.logical (db::LDPair (1, 5)).second, (unsigned int) 17); + EXPECT_EQ (lm.first_logical (db::LDPair (1, 6)).first, false); + EXPECT_EQ (lm.first_logical (db::LDPair (1, 5)).first, true); + EXPECT_EQ (lm.first_logical (db::LDPair (1, 5)).second, (unsigned int) 17); lm.map (db::LDPair (1, 0), db::LDPair (5,0), 18); - EXPECT_EQ (lm.logical (db::LDPair (2, 0)).first, true); - EXPECT_EQ (lm.logical (db::LDPair (2, 0)).second, (unsigned int) 18); - EXPECT_EQ (lm.logical (db::LDPair (0, 0)).first, false); + EXPECT_EQ (lm.first_logical (db::LDPair (2, 0)).first, true); + 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 (17), "1/5"); @@ -62,16 +62,16 @@ TEST(1) lm.map_expr ("XP;10/7-8 : XN", 13); EXPECT_EQ (lm.mapping_str (13), "10/7-8;XP : XN"); - EXPECT_EQ (lm.logical ("XP").second, (unsigned int) 13); - EXPECT_EQ (lm.logical ("XP").first, true); - EXPECT_EQ (lm.logical (db::LDPair(10, 6)).first, false); - EXPECT_EQ (lm.logical (db::LDPair(10, 7)).first, true); - EXPECT_EQ (lm.logical (db::LDPair(10, 7)).second, (unsigned int) 13); + EXPECT_EQ (lm.first_logical ("XP").second, (unsigned int) 13); + EXPECT_EQ (lm.first_logical ("XP").first, true); + EXPECT_EQ (lm.first_logical (db::LDPair(10, 6)).first, false); + EXPECT_EQ (lm.first_logical (db::LDPair(10, 7)).first, true); + EXPECT_EQ (lm.first_logical (db::LDPair(10, 7)).second, (unsigned int) 13); EXPECT_EQ (lm.mapping (13).to_string (), "XN (10/7)"); lm.clear (); - EXPECT_EQ (lm.logical (db::LDPair(10, 7)).first, false); + 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"); } @@ -349,55 +349,55 @@ TEST(6) EXPECT_EQ (layers_to_string (ly), "1/0,3/10"); std::pair p; - p = lm.logical (db::LayerProperties (1, 0)); + p = lm.first_logical (db::LayerProperties (1, 0)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 0); - p = lm.logical (db::LayerProperties (2, 0)); + p = lm.first_logical (db::LayerProperties (2, 0)); EXPECT_EQ (p.first, false); - p = lm.logical (db::LayerProperties (3, 0)); + p = lm.first_logical (db::LayerProperties (3, 0)); EXPECT_EQ (p.first, false); - p = lm.logical (db::LayerProperties (3, 10)); + p = lm.first_logical (db::LayerProperties (3, 10)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 1); - p = lm.logical (db::LayerProperties (3, 99)); + p = lm.first_logical (db::LayerProperties (3, 99)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 1); EXPECT_EQ (layers_to_string (ly), "1/0,3/10"); // this will create layer 2/0 in the layout - p = lm.logical (db::LayerProperties (2, 0), ly); + p = lm.first_logical (db::LayerProperties (2, 0), ly); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 2); EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0"); - p = lm.logical (db::LayerProperties (2, 0)); + p = lm.first_logical (db::LayerProperties (2, 0)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 2); - p = lm.logical (db::LayerProperties (2, 0), ly); + p = lm.first_logical (db::LayerProperties (2, 0), ly); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 2); EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0"); // this will create layer 2/42 in the layout - p = lm.logical (db::LayerProperties (2, 42), ly); + p = lm.first_logical (db::LayerProperties (2, 42), ly); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 3); EXPECT_EQ (layers_to_string (ly), "1/0,3/10,2/0,2/42"); - p = lm.logical (db::LayerProperties (2, 42)); + p = lm.first_logical (db::LayerProperties (2, 42)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 3); - p = lm.logical (db::LayerProperties (2, 42), ly); + p = lm.first_logical (db::LayerProperties (2, 42), ly); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 3); @@ -429,19 +429,91 @@ TEST(7) EXPECT_EQ (layers_to_string (ly), "85/0,185/0,,"); std::pair p; - p = lm.logical (db::LayerProperties (85, 0)); + p = lm.first_logical (db::LayerProperties (85, 0)); EXPECT_EQ (p.first, false); EXPECT_EQ (p.second, (unsigned int) 0); - p = lm.logical (db::LayerProperties (185, 0)); + p = lm.first_logical (db::LayerProperties (185, 0)); EXPECT_EQ (p.first, false); EXPECT_EQ (p.second, (unsigned int) 0); - p = lm.logical (db::LayerProperties (10000, 0)); + p = lm.first_logical (db::LayerProperties (10000, 0)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 1); - p = lm.logical (db::LayerProperties (10001, 0)); + p = lm.first_logical (db::LayerProperties (10001, 0)); EXPECT_EQ (p.first, true); EXPECT_EQ (p.second, (unsigned int) 0); } + +// multi-mapping, unmapping +TEST(8) +{ + db::LayerMap lm; + + unsigned int n = 0; + + // refinement + // all + lm.mmap_expr ("*/*", n++); + EXPECT_EQ (lm.mapping_str (0), "*/*"); + EXPECT_EQ (lm.to_string (), + "layer_map('*/*')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // some + lm.mmap_expr ("*/1-10", n++); + EXPECT_EQ (lm.to_string (), + "layer_map('+*/0,1-10,11-*';'+*/1-10')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // others + 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')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // 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 (2), "+*/5,15"); + EXPECT_EQ (lm.mapping_str (3), ""); + + lm = db::LayerMap (); + n = 0; + + // refinement + // all + lm.mmap_expr ("*/*", n++); + EXPECT_EQ (lm.mapping_str (0), "*/*"); + EXPECT_EQ (lm.to_string (), + "layer_map('*/*')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // some + lm.mmap_expr ("1-10/*", n++); + EXPECT_EQ (lm.to_string (), + "layer_map('+0/*;1-10/*;11-*/*';'+1-10/*')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // others + 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/*')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // 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 (2), "+5/*;15/*"); + EXPECT_EQ (lm.mapping_str (3), ""); +} + diff --git a/src/lay/lay/laySearchReplaceDialog.cc b/src/lay/lay/laySearchReplaceDialog.cc index 41b591104..e9ef8b94f 100644 --- a/src/lay/lay/laySearchReplaceDialog.cc +++ b/src/lay/lay/laySearchReplaceDialog.cc @@ -504,7 +504,7 @@ SearchReplaceResults::export_layout (db::Layout &layout) std::map::const_iterator lm = m_lp_map.find (layer); if (lm != m_lp_map.end ()) { - std::pair ll = insert_lm.logical (lm->second); + std::pair ll = insert_lm.first_logical (lm->second); if (! ll.first) { layer = layout.insert_layer (lm->second); insert_lm.map (lm->second, layer, lm->second); diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc index cb023d887..5517001d8 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc @@ -381,7 +381,7 @@ DXFReader::do_read (db::Layout &layout, db::cell_index_type top) { // create the zero layer - this is not mapped to GDS but can be specified in the layer mapping as // a layer named "0". - std::pair ll = layer_map ().logical (zero_layer_name, layout); + std::pair ll = layer_map ().first_logical (zero_layer_name, layout); if (ll.first) { // create the layer if it is not part of the layout yet. diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc index d79793638..7111089d9 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc @@ -184,7 +184,7 @@ GDS2ReaderBase::finish_element (db::PropertiesRepository &rep) std::pair GDS2ReaderBase::open_dl (db::Layout &layout, const LDPair &dl, bool create) { - std::pair ll = m_layer_map.logical (dl, layout); + std::pair ll = m_layer_map.first_logical (dl, layout); if (ll.first) { return ll; diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc index 838260bf3..7361c67a2 100644 --- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc +++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc @@ -332,7 +332,7 @@ TEST(2) db::Layout layout_piece (&m); layout_piece = layout; - std::pair jj = map_full.logical (pairs[i]); + std::pair jj = map_full.first_logical (pairs[i]); EXPECT_EQ (jj.first, true); for (unsigned int j = 0; j < layout_piece.layers(); ++j) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 2c47e2984..f68700609 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -1180,7 +1180,7 @@ 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.logical (lp, layout); + std::pair ll = m_layer_map.first_logical (lp, layout); if (ll.first) { @@ -1300,10 +1300,10 @@ 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.logical (name, layout); + std::pair ll = m_layer_map.first_logical (name, layout); bool generic_match = false; if (! ll.first) { - ll = m_layer_map.logical (n, layout); + ll = m_layer_map.first_logical (n, layout); generic_match = true; } else if (n == name) { // no suffix defined in tech component -> treat as generic match and combine datatypes diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc index 3bf5485a5..131fb3e9a 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc @@ -557,7 +557,7 @@ OASISReader::warn (const std::string &msg) std::pair OASISReader::open_dl (db::Layout &layout, const LDPair &dl, bool create) { - std::pair ll = m_layer_map.logical (dl, layout); + std::pair ll = m_layer_map.first_logical (dl, layout); if (ll.first) { return ll; From 3e249b0b54f31e6b9b075e3eaa7453e90e7cbe8a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 15 Dec 2020 23:51:01 +0100 Subject: [PATCH 12/29] WIP: More tests for layer multi-mapping --- src/db/unit_tests/dbStreamLayerTests.cc | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/db/unit_tests/dbStreamLayerTests.cc b/src/db/unit_tests/dbStreamLayerTests.cc index 353e31693..6b0b478b0 100644 --- a/src/db/unit_tests/dbStreamLayerTests.cc +++ b/src/db/unit_tests/dbStreamLayerTests.cc @@ -446,6 +446,18 @@ TEST(7) EXPECT_EQ (p.second, (unsigned int) 0); } +static std::string set2string (const std::set &set) +{ + std::string s; + for (std::set::const_iterator i = set.begin (); i != set.end (); ++i) { + if (i != set.begin ()) { + s += ","; + } + s += tl::to_string (*i); + } + return s; +} + // multi-mapping, unmapping TEST(8) { @@ -477,6 +489,12 @@ TEST(8) ); EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + EXPECT_EQ (set2string (lm.logical (db::LDPair (0, 1000))), "0"); + EXPECT_EQ (set2string (lm.logical (db::LDPair (1, 1000))), "0"); + EXPECT_EQ (set2string (lm.logical (db::LDPair (0, 5))), "0,1,2"); + EXPECT_EQ (set2string (lm.logical (db::LDPair (0, 15))), "0,2"); + 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"); @@ -510,10 +528,33 @@ TEST(8) ); EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + EXPECT_EQ (set2string (lm.logical (db::LDPair (1000, 0))), "0"); + EXPECT_EQ (set2string (lm.logical (db::LDPair (1000, 1))), "0"); + EXPECT_EQ (set2string (lm.logical (db::LDPair (5, 0))), "0,1,2"); + EXPECT_EQ (set2string (lm.logical (db::LDPair (15, 0))), "0,2"); + 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 (2), "+5/*;15/*"); EXPECT_EQ (lm.mapping_str (3), ""); + + lm = db::LayerMap (); + n = 0; + + lm.mmap_expr ("*/*", n++); + EXPECT_EQ (lm.mapping_str (0), "*/*"); + EXPECT_EQ (lm.to_string (), + "layer_map('*/*')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); + + // 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')" + ); + EXPECT_EQ (db::LayerMap::from_string_file_format (lm.to_string_file_format ()).to_string (), lm.to_string ()); } From 91de3709015e583eb83a2cd294c5a13a7537f39c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 16 Dec 2020 23:02:01 +0100 Subject: [PATCH 13/29] WIP: bugfix, RBA tests. --- src/db/db/dbStreamLayers.cc | 8 +++--- testdata/ruby/dbLayout.rb | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc index e507ddea9..f86db8273 100644 --- a/src/db/db/dbStreamLayers.cc +++ b/src/db/db/dbStreamLayers.cc @@ -502,10 +502,10 @@ void LayerMap::mmap (const LayerProperties &f, unsigned int l) { if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) { - map (db::LDPair (f.layer, f.datatype), l); + mmap (db::LDPair (f.layer, f.datatype), l); } if (! f.name.empty ()) { - map (f.name, l); + mmap (f.name, l); } } @@ -525,10 +525,10 @@ void LayerMap::mmap (const LayerProperties &f, unsigned int l, const LayerProperties &t) { if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) { - map (db::LDPair (f.layer, f.datatype), l, t); + mmap (db::LDPair (f.layer, f.datatype), l, t); } if (! f.name.empty ()) { - map (f.name, l, t); + mmap (f.name, l, t); } } diff --git a/testdata/ruby/dbLayout.rb b/testdata/ruby/dbLayout.rb index e5ff45791..33a1decae 100644 --- a/testdata/ruby/dbLayout.rb +++ b/testdata/ruby/dbLayout.rb @@ -30,7 +30,11 @@ class DBLayout_TestClass < TestBase lmap = RBA::LayerMap::new lmap.map( "1/0", 0 ) + assert_equal(lmap.is_mapped(RBA::LayerInfo::new(1, 0)), true) + assert_equal(lmap.is_mapped(RBA::LayerInfo::new(1, 1)), false) + assert_equal(lmap.is_mapped(RBA::LayerInfo::new(2, 2)), false) lmap.map( "2/2", 0 ) + assert_equal(lmap.is_mapped(RBA::LayerInfo::new(2, 2)), true) lmap.map( "10/2", 0 ) assert_equal( lmap.mapping_str(0), "1/0;2/2;10/2" ) @@ -85,6 +89,55 @@ class DBLayout_TestClass < TestBase assert_equal( lmap.mapping_str(0), "2/2 : 4/4" ) assert_equal( lmap.mapping(0).to_s, "4/4" ) assert_equal( lmap.mapping(2).to_s, "5/5" ) + + lmap = RBA::LayerMap::new + + lmap.map("*/*", 0) + lmap.unmap(RBA::LayerInfo::new(5, 10)) + assert_equal(lmap.mapping_str(0), "0-4/*;5/0-9,11-*;6-*/*") + + lmap.clear + lmap.map("*/*", 0) + lmap.unmap(RBA::LayerInfo::new(5, 10), RBA::LayerInfo::new(16, 21)) + assert_equal(lmap.mapping_str(0), "0-4/*;5-16/0-9,22-*;17-*/*") + + lmap.clear + lmap.map("*/*", 0) + lmap.unmap("5-16/10-21") + assert_equal(lmap.mapping_str(0), "0-4/*;5-16/0-9,22-*;17-*/*") + + 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(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(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(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(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(1), "+5-16/10-21") + + assert_equal(lmap.logicals(RBA::LayerInfo::new(5, 10)), [ 0, 1 ]) + assert_equal(lmap.logicals(RBA::LayerInfo::new(0, 10)), [ 0 ]) end From 0fddf7f389cb2de7a837ca1d4d2c2c7d10e14878 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 16 Dec 2020 23:52:58 +0100 Subject: [PATCH 14/29] WIP: text edit feature for layer mapping edit widget. --- src/buddies/src/bd/bdReaderOptions.cc | 2 +- src/db/db/dbStreamLayers.cc | 33 ++- src/db/db/dbStreamLayers.h | 16 ++ src/laybasic/laybasic/LayerMappingWidget.ui | 210 ++++++++++-------- .../laybasic/layLayerMappingWidget.cc | 49 +++- src/laybasic/laybasic/layLayerMappingWidget.h | 3 + 6 files changed, 199 insertions(+), 114 deletions(-) diff --git a/src/buddies/src/bd/bdReaderOptions.cc b/src/buddies/src/bd/bdReaderOptions.cc index 8a331dda6..dec684c29 100644 --- a/src/buddies/src/bd/bdReaderOptions.cc +++ b/src/buddies/src/bd/bdReaderOptions.cc @@ -604,7 +604,7 @@ void GenericReaderOptions::set_layer_map (const std::string &lm) int l = 0; while (! ex.at_end ()) { - m_layer_map.map_expr (ex, l); + m_layer_map.add_expr (ex, l); ex.test ("//"); ++l; } diff --git a/src/db/db/dbStreamLayers.cc b/src/db/db/dbStreamLayers.cc index f86db8273..eb1260601 100644 --- a/src/db/db/dbStreamLayers.cc +++ b/src/db/db/dbStreamLayers.cc @@ -738,6 +738,7 @@ LayerMap::unmap (const LDPair &p1, const LDPair &p2) } } + void LayerMap::unmap_expr (const std::string &expr) { @@ -838,6 +839,26 @@ LayerMap::to_string_file_format () const return os.str (); } +void +LayerMap::add_expr (const std::string &expr, unsigned int l) +{ + tl::Extractor ex (expr.c_str ()); + add_expr (ex, l); + ex.expect_end (); +} + +void +LayerMap::add_expr (tl::Extractor &ex, unsigned int l) +{ + if (ex.test ("+")) { + mmap_expr (ex, l); + } else if (ex.test ("-")) { + unmap_expr (ex); + } else { + map_expr (ex, l); + } +} + db::LayerMap LayerMap::from_string_file_format (const std::string &s) { @@ -860,13 +881,7 @@ LayerMap::from_string_file_format (const std::string &s) } else { if (! ex.at_end ()) { - if (ex.test ("+")) { - lm.mmap_expr (ex, l); - } else if (ex.test ("-")) { - lm.unmap_expr (ex); - } else { - lm.map_expr (ex, l); - } + lm.add_expr (ex, l); if (ex.test ("#") || ex.test ("//")) { // ignore comments } else { @@ -901,7 +916,7 @@ namespace tl while (! ex.test (")") && ! ex.at_end ()) { std::string m; ex.read_word_or_quoted (m); - t.map_expr (m, l); + t.add_expr (m, l); ++l; ex.test (";"); } @@ -921,7 +936,7 @@ namespace tl while (! ex.test (")") && ! ex.at_end ()) { std::string m; ex.read_word_or_quoted (m); - t.map_expr (m, l); + t.add_expr (m, l); ++l; ex.test (";"); } diff --git a/src/db/db/dbStreamLayers.h b/src/db/db/dbStreamLayers.h index 26c15804a..61eaad77a 100644 --- a/src/db/db/dbStreamLayers.h +++ b/src/db/db/dbStreamLayers.h @@ -521,6 +521,22 @@ public: */ void unmap_expr (tl::Extractor &ex); + /** + * @brief Generic expression mapping + * + * This generic mapping function takes a mapping expression. If it starts with "+", + * "mmap" is used, if it starts with "-", "unmap" is used. Otherwise, "map" is used. + */ + void add_expr (const std::string &expr, unsigned int l); + + /** + * @brief Generic expression mapping + * + * This generic mapping function takes a mapping expression. If it starts with "+", + * "mmap" is used, if it starts with "-", "unmap" is used. Otherwise, "map" is used. + */ + void add_expr (tl::Extractor &ex, unsigned int l); + /** * @brief Prepares a layer mapping object for reading * diff --git a/src/laybasic/laybasic/LayerMappingWidget.ui b/src/laybasic/laybasic/LayerMappingWidget.ui index a343b33ce..5fd4d65d7 100644 --- a/src/laybasic/laybasic/LayerMappingWidget.ui +++ b/src/laybasic/laybasic/LayerMappingWidget.ui @@ -6,8 +6,8 @@ 0 0 - 446 - 205 + 536 + 290 @@ -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^_Mi&#BJM=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