diff --git a/src/db/db/dbLayoutUtils.h b/src/db/db/dbLayoutUtils.h index 07ba86332..badbf8ae6 100644 --- a/src/db/db/dbLayoutUtils.h +++ b/src/db/db/dbLayoutUtils.h @@ -42,7 +42,7 @@ namespace db * * This implementation will create new layers if required. */ -class DirectLayerMapping +class DB_PUBLIC DirectLayerMapping : public ImportLayerMapping { public: diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 07122526d..431ff911f 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -22,9 +22,11 @@ #include "dbLEFDEFImporter.h" +#include "dbLayoutUtils.h" #include "tlStream.h" #include "tlProgress.h" +#include "tlFileUtils.h" #include @@ -74,7 +76,8 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_produce_special_routing (true), m_special_routing_suffix (""), m_special_routing_datatype (0), - m_separate_groups (false) + m_separate_groups (false), + m_consider_map_file (true) { // .. nothing yet .. } @@ -121,6 +124,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_special_routing_suffix (d.m_special_routing_suffix), m_special_routing_datatype (d.m_special_routing_datatype), m_separate_groups (d.m_separate_groups), + m_consider_map_file (d.m_consider_map_file), m_lef_files (d.m_lef_files) { // .. nothing yet .. @@ -142,8 +146,20 @@ LEFDEFReaderOptions::format_name () const // ----------------------------------------------------------------------------------- // LEFDEFLayerDelegate implementation +static db::LayerProperties lp_from_string (const std::string &ld) +{ + db::LayerProperties lp; + tl::Extractor ex (ld.c_str ()); + try { + ex.read (lp); + return lp; + } catch (...) { + return db::LayerProperties (0, 0); + } +} + LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc) - : m_create_layers (true), m_laynum (1), mp_tech_comp (tc) + : m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc) { if (tc) { m_layer_map = tc->layer_map (); @@ -158,8 +174,208 @@ LEFDEFReaderState::register_layer (const std::string &ln) ++m_laynum; } -std::pair +void +LEFDEFReaderState::set_explicit_layer_mapping (bool f) +{ + m_has_explicit_layer_mapping = f; + if (! f) { + m_layers.clear (); + } +} + +void +LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer) +{ + m_layers [std::make_pair (n, purpose)] = std::make_pair (true, layer); +} + +void +LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) +{ + tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; + + tl::InputFile file (path); + tl::InputStream file_stream (file); + tl::TextInputStream ts (file_stream); + + std::map purpose_translation; + purpose_translation ["LEFPIN"] = LEFPins; + purpose_translation ["PIN"] = Pins; + purpose_translation ["LEFOBS"] = Obstructions; + purpose_translation ["SPNET"] = SpecialRouting; + purpose_translation ["NET"] = Routing; + purpose_translation ["VIA"] = ViaGeometry; + purpose_translation ["BLOCKAGE"] = Blockage; + + std::map, db::LayerProperties> layer_map; + + if (tech_comp ()) { + + const db::LEFDEFReaderOptions &options = *tech_comp (); + + if (options.produce_placement_blockages ()) { + layer_map [std::make_pair (std::string (), Blockage)] = lp_from_string (options.placement_blockage_layer ()); + } + if (options.produce_cell_outlines ()) { + layer_map [std::make_pair (std::string (), Outline)] = lp_from_string (options.cell_outline_layer ()); + } + if (options.produce_regions ()) { + layer_map [std::make_pair (std::string (), Region)] = lp_from_string (options.region_layer ()); + } + + } + + while (! ts.at_end ()) { + + const std::string &l = ts.get_line (); + + tl::Extractor ex (l.c_str ()); + if (ex.at_end () || ex.test ("#")) { + + // ignore empty of comment lines + + } else { + + std::string w1, w2; + int layer = 0, datatype = 0; + + if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) { + + if (w1 == "DIEAREA") { + + layer_map [std::make_pair (std::string (), Outline)] = db::LayerProperties (layer, datatype, "OUTLINE"); + + } else if (w1 == "NAME") { + + // 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) { + 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, Label)] = db::LayerProperties (layer, datatype, final_name); + } + + } 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) + + std::set translated_purposes; + std::string purpose_str; + std::vector purposes = tl::split (w2, ","); + for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { + + std::map::const_iterator i = purpose_translation.find (tl::to_upper_case (*p)); + if (i != purpose_translation.end ()) { + + translated_purposes.insert (i->second); + + if (! purpose_str.empty ()) { + purpose_str += "/"; + } + purpose_str += i->first; + + } + } + + 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); + } + + } + + } + + } + + } + + set_explicit_layer_mapping (true); + + 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, lm.map_layer (i->second).second); + } + + // @@@ TODO: need to assign layer/datatype for all layers present. +} + +void +LEFDEFReaderState::import_map_file_heuristics (const std::string &main_path, db::Layout &layout) +{ + std::string input_dir = tl::absolute_path (main_path); + if (! tl::file_exists (input_dir)) { + return; + } + + std::string bn = tl::basename (tl::filename (main_path)); + std::vector map_files; + std::string map_file_exact; + + std::vector entries = tl::dir_entries (input_dir); + for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { + + if (tl::to_lower_case (tl::extension (*e)) == "map") { + + if (tl::basename (*e) == bn) { + map_file_exact = *e; + } else { + map_files.push_back (*e); + } + + } + + } + + try { + if (! map_file_exact.empty ()) { + read_map_file (tl::combine_path (input_dir, map_file_exact), layout); + } else if (map_files.size () == 1) { + read_map_file (tl::combine_path (input_dir, map_files.front ()), layout); + } + } catch (tl::Exception &ex) { + // ignore read errors on map file (this is a heuristics!) + tl::error << ex.msg (); + } +} + +std::pair LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose) +{ + std::map , std::pair >::const_iterator nl = m_layers.find (std::make_pair (n, purpose)); + if (nl == m_layers.end ()) { + + std::pair ll (false, 0); + + if (! m_has_explicit_layer_mapping) { + ll = open_layer_uncached (layout, n, purpose); + } + + m_layers.insert (std::make_pair (std::make_pair (n, purpose), ll)); + return ll; + + } else { + return nl->second; + } +} + +std::pair +LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n, LayerPurpose purpose) { if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) { @@ -167,21 +383,17 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu // as is "(name)". It's used for implementing the automatic map file import // feature. std::string ld; - std::string canonical_name; bool produce; if (purpose == Outline) { produce = mp_tech_comp->produce_cell_outlines (); ld = mp_tech_comp->cell_outline_layer (); - canonical_name = "(OUTLINE)"; } else if (purpose == Region) { produce = mp_tech_comp->produce_regions (); ld = mp_tech_comp->region_layer (); - canonical_name = "(REGION)"; } else { produce = mp_tech_comp->produce_placement_blockages (); ld = mp_tech_comp->placement_blockage_layer (); - canonical_name = "(BLK)"; } if (! produce) { @@ -203,10 +415,6 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu return ll; - } else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) { - - return ll; - } else if (! m_create_layers) { return std::pair (false, 0); @@ -256,74 +464,54 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu } // Note: "name" is the decorated name as provided by the tech component's - // x_suffix specifications. As this is a variable entity, we also provide - // a canonical name of the form "(layer,purpose)" where purpose is a - // predefined suffix. The canonical name is the last fallback. Hence this - // allows importing layer mapping files as canonical name mapping. + // x_suffix specifications. std::string name (n); int dt = 0; - std::string canonical_purpose; - if (mp_tech_comp) { switch (purpose) { case Routing: default: name += mp_tech_comp->routing_suffix (); - canonical_purpose = "NET"; dt += mp_tech_comp->routing_datatype (); break; case SpecialRouting: name += mp_tech_comp->special_routing_suffix (); - canonical_purpose = "SPNET"; dt += mp_tech_comp->special_routing_datatype (); break; case ViaGeometry: name += mp_tech_comp->via_geometry_suffix (); dt += mp_tech_comp->via_geometry_datatype (); - canonical_purpose = "VIA"; break; case Label: name += mp_tech_comp->labels_suffix (); dt += mp_tech_comp->labels_datatype (); - canonical_purpose = "LABEL"; break; case Pins: name += mp_tech_comp->pins_suffix (); dt += mp_tech_comp->pins_datatype (); - canonical_purpose = "PIN"; break; case LEFPins: name += mp_tech_comp->lef_pins_suffix (); dt += mp_tech_comp->lef_pins_datatype (); - canonical_purpose = "LEFPIN"; break; case Obstructions: name += mp_tech_comp->obstructions_suffix (); dt += mp_tech_comp->obstructions_datatype (); - canonical_purpose = "OBS"; break; case Blockage: name += mp_tech_comp->blockages_suffix (); dt += mp_tech_comp->blockages_datatype (); - canonical_purpose = "BLK"; break; } } - std::string canonical_name = std::string ("(") + n + "," + canonical_purpose + ")"; - std::pair ll = m_layer_map.logical (name, layout); if (ll.first) { return ll; - } else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) { - - // final fallback: try canonical name - return ll; - } else { ll = m_layer_map.logical (n, layout); @@ -341,14 +529,14 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu } else { - std::map , unsigned int>::const_iterator nl = m_layers.find (std::make_pair (n, purpose)); - if (nl == m_layers.end ()) { - unsigned int li = layout.insert_layer (db::LayerProperties (name)); - m_layer_map.map (db::LayerProperties (name), li); - m_layers.insert (std::make_pair (std::make_pair (n, purpose), li)); - return std::pair (true, li); + std::map , unsigned int>::const_iterator l = m_unassigned_layers.find (std::make_pair (n, purpose)); + if (l != m_unassigned_layers.end ()) { + return std::pair (true, l->second); } else { - return std::pair (true, nl->second); + unsigned int li = layout.insert_layer (db::LayerProperties (name)); + m_unassigned_layers.insert (std::make_pair (std::make_pair (n, purpose), li)); + m_layer_map.map (db::LayerProperties (name), li); + return std::pair (true, li); } } @@ -380,7 +568,7 @@ LEFDEFReaderState::finish (db::Layout &layout) used_numbers.insert (ln->second); } - for (std::map, unsigned int>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { + for (std::map, unsigned int>::const_iterator l = m_unassigned_layers.begin (); l != m_unassigned_layers.end (); ++l) { int dt = 0; switch (l->first.second) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 6c9adf325..df61cf62e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -515,6 +515,16 @@ public: m_separate_groups = f; } + bool consider_map_file () const + { + return m_consider_map_file; + } + + void set_consider_map_file (bool f) + { + m_consider_map_file = f; + } + private: bool m_read_all_layers; db::LayerMap m_layer_map; @@ -557,6 +567,7 @@ private: std::string m_special_routing_suffix; int m_special_routing_datatype; bool m_separate_groups; + bool m_consider_map_file; std::vector m_lef_files; }; @@ -592,7 +603,32 @@ public: LEFDEFReaderState (const LEFDEFReaderOptions *tc); /** - * @brief Set the layer map + * @brief Provides an explicit layer mapping + * This method is used when reading the layer map file. + */ + void map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer); + + /** + * @brief Provides an explicit layer mapping + * If this flag is set, the layer mapping specified in the reader options are ignored. + */ + void set_explicit_layer_mapping (bool f); + + /** + * @brief Reads a map file + */ + void read_map_file (const std::string &path, db::Layout &layout); + + /** + * @brief Imports a .map file present next to the input files + * "main_path" path of an input file (DEF). If a suitable .map file is found at this path, + * it is loaded into the reader state object. This will eventually disable any other layer + * mapping except for the global layers (region, outline, placement blockage). + */ + void import_map_file_heuristics (const std::string &main_path, db::Layout &layout); + + /** + * @brief Sets the layer map */ virtual void set_layer_map (const db::LayerMap &lm, bool create_layers) { @@ -601,7 +637,7 @@ public: } /** - * @brief Get the layer map + * @brief Gets the layer map */ const db::LayerMap &layer_map () const { @@ -609,7 +645,7 @@ public: } /** - * @brief Get the layer map (non-const version) + * @brief Gets the layer map (non-const version) */ db::LayerMap &layer_map () { @@ -655,13 +691,17 @@ public: } private: - std::map , unsigned int> m_layers; + std::map , std::pair > m_layers; + std::map , unsigned int> m_unassigned_layers; db::LayerMap m_layer_map; bool m_create_layers; + bool m_has_explicit_layer_mapping; int m_laynum; std::map m_default_number; std::map m_via_cells; const LEFDEFReaderOptions *mp_tech_comp; + + std::pair open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose); }; /** diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 699518e7a..f42a438e2 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -30,6 +30,7 @@ #include "dbLEFImporter.h" #include "dbDEFImporter.h" #include "dbLEFDEFImporter.h" +#include "dbLayoutUtils.h" namespace db { @@ -77,156 +78,6 @@ static bool is_def_format (const std::string &fn) return false; } -/** - * @brief Reads a map file - * - * NOTE: this is rather experimental ... no idea what is the specification of - * the map file. - */ -static void -read_map_file (const std::string &path, db::LEFDEFReaderState &layers) -{ - tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; - - db::LayerMap &lm = layers.layer_map (); - unsigned int n = lm.next_index (); - - tl::InputFile file (path); - tl::InputStream file_stream (file); - tl::TextInputStream ts (file_stream); - - std::map purpose_translation; - purpose_translation ["LEFPIN"] = "LEFPIN"; - purpose_translation ["PIN"] = "PIN"; - purpose_translation ["LEFOBS"] = "OBS"; - purpose_translation ["SPNET"] = "SPNET"; - purpose_translation ["NET"] = "NET"; - purpose_translation ["VIA"] = "VIA"; - purpose_translation ["BLOCKAGE"] = "BLK"; - - while (! ts.at_end ()) { - - const std::string &l = ts.get_line (); - - tl::Extractor ex (l.c_str ()); - if (ex.at_end () || ex.test ("#")) { - - // ignore empty of comment lines - - } else { - - std::string w1, w2; - int layer = 0, datatype = 0; - - if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) { - - if (w1 == "DIEAREA") { - - std::string canonical_name = "OUTLINE"; - lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); - - } else if (w1 == "NAME") { - - // 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) { - 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) { - std::string canonical_name = std::string ("(") + *l + ",LABEL)"; - lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); - } - ++n; - - } 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) - - std::vector translated_purposes; - std::vector purposes = tl::split (w2, ","); - for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { - std::map::const_iterator i = purpose_translation.find (tl::to_upper_case (*p)); - if (i != purpose_translation.end ()) { - translated_purposes.push_back (i->second); - } - } - - std::sort (translated_purposes.begin (), translated_purposes.end ()); - translated_purposes.erase (std::unique (translated_purposes.begin (), translated_purposes.end ()), translated_purposes.end ()); - std::string final_name = w1 + "." + tl::join (translated_purposes, "/"); - - for (std::vector::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) { - std::string canonical_name = std::string ("(") + w1 + "," + *p + ")"; - lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); - } - ++n; - - } - - } - - } - - } -} - -/** - * @brief Imports a .map file present next to the input files - */ -static void -import_map_file_heuristics (const std::string &main_path, db::LEFDEFReaderState &layers) -{ - std::string input_dir = tl::absolute_path (main_path); - if (! tl::file_exists (input_dir)) { - return; - } - - std::string bn = tl::basename (tl::filename (main_path)); - std::vector map_files; - std::string map_file_exact; - - std::vector entries = tl::dir_entries (input_dir); - for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { - - if (tl::to_lower_case (tl::extension (*e)) == "map") { - - if (tl::basename (*e) == bn) { - map_file_exact = *e; - } else { - map_files.push_back (*e); - } - - } - - } - - try { - if (! map_file_exact.empty ()) { - read_map_file (tl::combine_path (input_dir, map_file_exact), layers); - tl::log << layers.layer_map ().to_string_file_format (); // @@@ - } else if (map_files.size () == 1) { - read_map_file (tl::combine_path (input_dir, map_files.front ()), layers); - tl::log << layers.layer_map ().to_string_file_format (); // @@@ - } - } catch (tl::Exception &ex) { - // ignore read errors on map file (this is a heuristics!) - tl::error << ex.msg (); - } -} - class LEFDEFReader : public db::ReaderBase { @@ -275,7 +126,9 @@ private: db::LEFDEFReaderState state (lefdef_options); - import_map_file_heuristics (m_stream.absolute_path (), state); + if (lefdef_options->consider_map_file ()) { + state.import_map_file_heuristics (m_stream.absolute_path (), layout); + } state.prepare (layout); layout.dbu (lefdef_options->dbu ()); diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 6d31e64cc..14336a90b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -461,11 +461,25 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "This property has been added in version 0.26.5.\n" ) + gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"), - "@brief Gets a value indicating whether to create separate parent cells for individual groups.\n" + "@brief Sets a value indicating whether to create separate parent cells for individual groups.\n" "See \\seperate_groups for details about this property.\n" "\n" "This property has been added in version 0.26.5.\n" ) + + gsi::method ("consider_map_file", &db::LEFDEFReaderOptions::consider_map_file, + "@brief Gets a value indicating whether to consider reading .map files next to DEF files.\n" + "If this property is set to true (the default), the DEF reader will look for .map files next to the " + "DEF file. If such a file is found, it will be used to map DEF layers to layout layers. The layer mapping " + "settings specified in the reader options are ignored in this case.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + + gsi::method ("consider_map_file=", &db::LEFDEFReaderOptions::set_consider_map_file, gsi::arg ("flag"), + "@brief Sets a value indicating whether to consider reading .map files next to DEF files.\n" + "See \\consider_map_file for details about this property.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files, "@brief Gets the list technology LEF files to additionally import\n" "Returns a list of path names for technology LEF files to read in addition to the primary file. " diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index 845452c8e..1ae4b3c64 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -207,17 +207,13 @@ 4 - - - - Layout database unit - - - - - - - Via cell name prefix + + + + + 0 + 0 + @@ -234,6 +230,34 @@ + + + + Produce a parent cell for each group + + + + + + + Via cell name prefix + + + + + + + Layout database unit + + + + + + + Separate groups + + + @@ -244,27 +268,20 @@ - - - - - 0 - 0 - + + + + Consider map files - - + + - Produce a parent cell for each group + Look for .map files next to DEF files and use them to map layers - - - - - - Separate groups + + true @@ -517,13 +534,6 @@ - - - - Produce ... - - - @@ -764,6 +774,56 @@ + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Layer assignment is not used if a .map file is present for DEF layer mapping + + + + + + :/warn_16.png + + + + + + + + 1 + 0 + + + + Produce ... + + + + + + @@ -781,10 +841,7 @@ true - - - 6 - + 9 @@ -797,21 +854,14 @@ 4 - + Read all layers (additionally to the ones in the mapping table) - - - - Qt::Horizontal - - - - + @@ -833,6 +883,32 @@ + + + + + 0 + 0 + + + + This table is not used if a .map file is present for DEF layer mapping + + + + + + :/warn_16.png + + + + + + + Qt::Horizontal + + + @@ -881,12 +957,12 @@ setChecked(bool) - 186 - 598 + 229 + 838 - 155 - 553 + 198 + 701 diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index 16b70262d..fec570018 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -363,6 +363,7 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent) connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ())); connect (move_lef_files_up, SIGNAL (clicked ()), this, SLOT (move_lef_files_up_clicked ())); connect (move_lef_files_down, SIGNAL (clicked ()), this, SLOT (move_lef_files_down_clicked ())); + connect (consider_map_file, SIGNAL (stateChanged (int)), this, SLOT (consider_map_file_state_changed ())); lay::activate_help_links (help_label); } @@ -450,6 +451,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_labels_suffix (tl::to_string (suffix_labels->text ())); data->set_labels_datatype (datatype_labels->text ().toInt ()); data->set_separate_groups (separate_groups->isChecked ()); + data->set_consider_map_file (consider_map_file->isChecked ()); data->clear_lef_files (); for (int i = 0; i < lef_files->count (); ++i) { @@ -510,6 +512,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options suffix_labels->setText (tl::to_qstring (data->labels_suffix ())); datatype_labels->setText (QString::number (data->labels_datatype ())); separate_groups->setChecked (data->separate_groups ()); + consider_map_file->setChecked (data->consider_map_file ()); checkbox_changed (); @@ -526,6 +529,13 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options } } +void +LEFDEFReaderOptionsEditor::consider_map_file_state_changed () +{ + warn1->setVisible (consider_map_file->isChecked ()); + warn2->setVisible (consider_map_file->isChecked ()); +} + void LEFDEFReaderOptionsEditor::checkbox_changed () { diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h index 7234c76aa..1da4f81b2 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h @@ -98,6 +98,7 @@ private slots: void del_lef_files_clicked (); void move_lef_files_up_clicked (); void move_lef_files_down_clicked (); + void consider_map_file_state_changed (); private: tl::weak_ptr mp_tech; diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 45b21683b..97e36f7d9 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -69,7 +69,15 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file while (! ex.at_end ()) { - if (ex.test ("def:")) { + if (ex.test ("map:")) { + + std::string fn = fn_path, f; + ex.read_word_or_quoted (f); + fn += f; + + ld.read_map_file (fn, layout); + + } else if (ex.test ("def:")) { std::string fn = fn_path, f; ex.read_word_or_quoted (f); @@ -230,6 +238,7 @@ TEST(15) TEST(16) { run_test (_this, "def7", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au.oas.gz", default_options ()); + run_test (_this, "def7", "map:in.map+lef:cells.lef+lef:tech.lef+def:in.def.gz", "au_with_map_file.oas.gz", default_options ()); } TEST(17) diff --git a/testdata/ruby/dbReaders.rb b/testdata/ruby/dbReaders.rb index c874c782f..b17092355 100644 --- a/testdata/ruby/dbReaders.rb +++ b/testdata/ruby/dbReaders.rb @@ -345,6 +345,10 @@ class DBReaders_TestClass < TestBase conf.separate_groups = true assert_equal(conf.separate_groups, true) + assert_equal(conf.consider_map_file, true) + conf.consider_map_file = false + assert_equal(conf.consider_map_file, false) + assert_equal(conf.lef_files.join(","), "") conf.lef_files = [ "u.lef", "v.lef" ] assert_equal(conf.lef_files.join(","), "u.lef,v.lef")