From 0d848d0597c71ed6395daadf7f57182aa6f9de82 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 4 May 2021 22:56:03 +0200 Subject: [PATCH] Added LEF macro file list to API and UI --- src/lay/lay/layMainWindow.cc | 63 +-- src/lay/lay/layMainWindow.h | 5 + .../lefdef/db_plugin/dbLEFDEFImporter.cc | 1 + .../lefdef/db_plugin/dbLEFDEFImporter.h | 49 +++ .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 232 ++++++----- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 49 ++- .../LEFDEFTechnologyComponentEditor.ui | 369 +++++++++++++----- .../lefdef/lay_plugin/layLEFDEFImport.cc | 63 +-- .../lay_plugin/layLEFDEFImportDialogs.cc | 226 +++++++---- .../lay_plugin/layLEFDEFImportDialogs.h | 9 + testdata/ruby/dbReaders.rb | 4 + 11 files changed, 693 insertions(+), 377 deletions(-) diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 9a33b027f..1078ac0c6 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -394,34 +394,7 @@ MainWindow::MainWindow (QApplication *app, const char *name, bool undo_enabled) // layout file dialog - std::string fmts = tl::to_string (QObject::tr ("All layout files (")); - for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { - if (rdr != tl::Registrar::begin ()) { - fmts += " "; - } - std::string f = rdr->file_format (); - if (!f.empty ()) { - const char *fp = f.c_str (); - while (*fp && *fp != '(') { - ++fp; - } - if (*fp) { - ++fp; - } - while (*fp && *fp != ')') { - fmts += *fp++; - } - } - } - fmts += ");;"; - for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { - if (!rdr->file_format ().empty ()) { - fmts += rdr->file_format (); - fmts += ";;"; - } - } - fmts += tl::to_string (QObject::tr ("All files (*)")); - mp_layout_fdia = new lay::FileDialog (this, tl::to_string (QObject::tr ("Layout File")), fmts); + mp_layout_fdia = new lay::FileDialog (this, tl::to_string (QObject::tr ("Layout File")), all_layout_file_formats ()); // save & load layout options mp_layout_save_as_options = new lay::SaveLayoutAsOptionsDialog (this, tl::to_string (QObject::tr ("Save Layout Options"))); @@ -478,6 +451,40 @@ MainWindow::~MainWindow () mp_assistant = 0; } +std::string +MainWindow::all_layout_file_formats () const +{ + std::string fmts = tl::to_string (QObject::tr ("All layout files (")); + for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { + if (rdr != tl::Registrar::begin ()) { + fmts += " "; + } + std::string f = rdr->file_format (); + if (!f.empty ()) { + const char *fp = f.c_str (); + while (*fp && *fp != '(') { + ++fp; + } + if (*fp) { + ++fp; + } + while (*fp && *fp != ')') { + fmts += *fp++; + } + } + } + fmts += ");;"; + for (tl::Registrar::iterator rdr = tl::Registrar::begin (); rdr != tl::Registrar::end (); ++rdr) { + if (!rdr->file_format ().empty ()) { + fmts += rdr->file_format (); + fmts += ";;"; + } + } + fmts += tl::to_string (QObject::tr ("All files (*)")); + + return fmts; +} + void MainWindow::init_menu () { diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index a5c02aac7..b5e37b283 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -526,6 +526,11 @@ public: */ void open (int mode); + /** + * @brief Gets a format string with all registered layout formats + */ + std::string all_layout_file_formats () const; + /** * @brief An event indicating that the current view has changed * This event is fired if the current view was changed. diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 31cd62093..3d89896f5 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -580,6 +580,7 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions & m_map_file = d.m_map_file; m_macro_resolution_mode = d.m_macro_resolution_mode; m_lef_files = d.m_lef_files; + m_macro_layout_files = d.m_macro_layout_files; m_read_lef_with_def = d.m_read_lef_with_def; set_macro_layouts (d.macro_layouts ()); } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 203451541..c022d0735 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -877,6 +877,36 @@ public: return res; } + void clear_macro_layout_files () + { + m_macro_layout_files.clear (); + } + + void push_macro_layout_file (const std::string &l) + { + m_macro_layout_files.push_back (l); + } + + std::vector::const_iterator begin_macro_layout_files () const + { + return m_macro_layout_files.begin (); + } + + std::vector::const_iterator end_macro_layout_files () const + { + return m_macro_layout_files.end (); + } + + std::vector macro_layout_files () const + { + return m_macro_layout_files; + } + + void set_macro_layout_files (const std::vector &lf) + { + m_macro_layout_files = lf; + } + private: bool m_read_all_layers; db::LayerMap m_layer_map; @@ -939,6 +969,7 @@ private: bool m_read_lef_with_def; std::vector m_lef_files; tl::weak_collection m_macro_layouts; + std::vector m_macro_layout_files; }; /** @@ -1599,6 +1630,24 @@ private: const std::string &next (); }; +class DB_PLUGIN_PUBLIC LEFDEFReader + : public db::ReaderBase +{ +public: + LEFDEFReader (tl::InputStream &s); + + virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options); + virtual const db::LayerMap &read (db::Layout &layout); + + virtual const char *format () const; + + const db::LayerMap &read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef); + +private: + tl::InputStream &m_stream; + db::LayerMap m_layer_map; +}; + } #endif diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 30d50f357..cb6c92ec0 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -80,112 +80,108 @@ static bool is_def_format (const std::string &fn) return false; } -class LEFDEFReader - : public db::ReaderBase +// --------------------------------------------------------------- +// LEFDEFReader implementation + +LEFDEFReader::LEFDEFReader (tl::InputStream &s) + : m_stream (s) { -public: + // .. nothing yet .. +} - LEFDEFReader (tl::InputStream &s) - : m_stream (s) - { - // .. nothing yet .. +const db::LayerMap & +LEFDEFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) +{ + return read_lefdef (layout, options, is_lef_format (m_stream.filename ())); +} + +const db::LayerMap & +LEFDEFReader::read (db::Layout &layout) +{ + return read_lefdef (layout, db::LoadLayoutOptions (), is_lef_format (m_stream.filename ())); +} + +const char * +LEFDEFReader::format () const +{ + return "LEFDEF"; +} + +const db::LayerMap & +LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef) +{ + const db::LEFDEFReaderOptions *lefdef_options = dynamic_cast (options.get_options (format ())); + db::LEFDEFReaderOptions effective_options; + if (lefdef_options) { + effective_options = *lefdef_options; } - virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options) - { - return read_lefdef (layout, options, is_lef_format (m_stream.filename ())); - } + db::LEFDEFReaderState state (&effective_options, layout, tl::dirname (m_stream.absolute_path ())); - virtual const db::LayerMap &read (db::Layout &layout) - { - return read_lefdef (layout, db::LoadLayoutOptions (), is_lef_format (m_stream.filename ())); - } + layout.dbu (effective_options.dbu ()); - virtual const char *format () const - { - return "LEFDEF"; - } + if (import_lef) { -private: - tl::InputStream &m_stream; - db::LayerMap m_layer_map; + // 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 = 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 ())); + + tl::InputStream lef_stream (lp); + tl::log << tl::to_string (tr ("Reading")) << " " << lp; + importer.read (lef_stream, layout, state); - 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 ())); - db::LEFDEFReaderOptions effective_options; - if (lefdef_options) { - effective_options = *lefdef_options; } - db::LEFDEFReaderState state (&effective_options, layout, tl::dirname (m_stream.absolute_path ())); + tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); + importer.read (m_stream, layout, state); - layout.dbu (effective_options.dbu ()); + importer.finish_lef (layout); - if (import_lef) { + } else { - // 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 DEF file"))); - tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file"))); + DEFImporter importer; - db::LEFImporter importer; + for (std::vector::const_iterator l = effective_options.begin_lef_files (); l != effective_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 ())); - std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ())); + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp); - tl::InputStream lef_stream (lp); - tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read (lef_stream, layout, state); + tl::InputStream lef_stream (lp); + tl::log << tl::to_string (tr ("Reading")) << " " << lp; + importer.read_lef (lef_stream, layout, state); - } + } - tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); - importer.read (m_stream, layout, state); + // Additionally read all LEF files next to the DEF file - importer.finish_lef (layout); + if (effective_options.read_lef_with_def ()) { - } else { + std::string input_dir = tl::absolute_path (m_stream.absolute_path ()); - tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file"))); + if (tl::file_exists (input_dir)) { - DEFImporter importer; + std::vector entries = tl::dir_entries (input_dir, true, false, true); + for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { - for (std::vector::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) { + if (is_lef_format (*e)) { - std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ())); + std::string lp = tl::combine_path (input_dir, *e); - tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp); + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp); - tl::InputStream lef_stream (lp); - tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read_lef (lef_stream, layout, state); - - } - - // Additionally read all LEF files next to the DEF file - - if (effective_options.read_lef_with_def ()) { - - std::string input_dir = tl::absolute_path (m_stream.absolute_path ()); - - if (tl::file_exists (input_dir)) { - - std::vector entries = tl::dir_entries (input_dir, true, false, true); - for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { - - if (is_lef_format (*e)) { - - std::string lp = tl::combine_path (input_dir, *e); - - tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp); - - tl::InputStream lef_stream (lp); - tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read_lef (lef_stream, layout, state); - - } + tl::InputStream lef_stream (lp); + tl::log << tl::to_string (tr ("Reading")) << " " << lp; + importer.read_lef (lef_stream, layout, state); } @@ -193,46 +189,69 @@ private: } - tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); - importer.read (m_stream, layout, state); + } - // Resolve unresolved COMPONENT cells + tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); + importer.read (m_stream, layout, state); - std::map foreign_cells = state.foreign_cells (); - db::cell_index_type seen = std::numeric_limits::max (); + // Resolve unresolved COMPONENT cells - std::vector macro_layouts = effective_options.macro_layouts (); - for (std::vector::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) { + std::map foreign_cells = state.foreign_cells (); + db::cell_index_type seen = std::numeric_limits::max (); - std::vector target_cells, source_cells; + std::vector macro_layouts = effective_options.macro_layouts (); - // collect the cells to pull in - for (std::map::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) { - if (f->second != seen) { - std::pair cp = (*m)->cell_by_name (f->first.c_str ()); - if (cp.first) { - target_cells.push_back (f->second); - source_cells.push_back (cp.second); - layout.cell (f->second).set_ghost_cell (false); - f->second = seen; - } - } - } + // Additionally read the layouts from the given paths + tl::shared_collection macro_layout_object_holder; + for (std::vector::const_iterator l = effective_options.begin_macro_layout_files (); l != effective_options.end_macro_layout_files (); ++l) { - db::CellMapping cm; - cm.create_multi_mapping_full (layout, target_cells, **m, source_cells); - layout.copy_tree_shapes (**m, cm); + std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ())); - } + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF macro layout file: ")) + lp); + + tl::InputStream macro_layout_stream (lp); + tl::log << tl::to_string (tr ("Reading")) << " " << lp; + db::Layout *new_layout = new db::Layout (false); + macro_layout_object_holder.push_back (new_layout); + macro_layouts.push_back (new_layout); + + db::Reader reader (macro_layout_stream); + reader.read (*new_layout, options); } - state.finish (layout); + for (std::vector::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) { + + std::vector target_cells, source_cells; + + // collect the cells to pull in + for (std::map::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) { + if (f->second != seen) { + std::pair cp = (*m)->cell_by_name (f->first.c_str ()); + if (cp.first) { + target_cells.push_back (f->second); + source_cells.push_back (cp.second); + layout.cell (f->second).set_ghost_cell (false); + f->second = seen; + } + } + } + + db::CellMapping cm; + cm.create_multi_mapping_full (layout, target_cells, **m, source_cells); + layout.copy_tree_shapes (**m, cm); + + } - m_layer_map = state.layer_map (); - return m_layer_map; } -}; + + state.finish (layout); + + m_layer_map = state.layer_map (); + return m_layer_map; +} + +// --------------------------------------------------------------- namespace { @@ -371,6 +390,7 @@ class LEFDEFFormatDeclaration tl::make_member (&LEFDEFReaderOptions::special_routing_datatype_str, &LEFDEFReaderOptions::set_special_routing_datatype_str, "special-routing-datatype-string") + tl::make_member (&LEFDEFReaderOptions::via_cellname_prefix, &LEFDEFReaderOptions::set_via_cellname_prefix, "via-cellname-prefix") + tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") + + tl::make_member (&LEFDEFReaderOptions::begin_macro_layout_files, &LEFDEFReaderOptions::end_macro_layout_files, &LEFDEFReaderOptions::push_macro_layout_file, "macro_layout-files") + tl::make_member (&LEFDEFReaderOptions::read_lef_with_def, &LEFDEFReaderOptions::set_read_lef_with_def, "read-lef-with-def") + tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) + tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") + diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 18d0dba1e..3bf4f4ad4 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -119,7 +119,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "The setter is \\layer_map=. \\create_other_layers= is available to control whether layers " "not specified in the layer mapping table shall be created automatically." ) + - gsi::method ("layer_map=", &db::LEFDEFReaderOptions::set_layer_map, + gsi::method ("layer_map=", &db::LEFDEFReaderOptions::set_layer_map, gsi::arg ("m"), "@brief Sets the layer map to be used for the LEF/DEF reader\n" "See \\layer_map for details." ) + @@ -127,7 +127,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Gets a value indicating whether layers not mapped in the layer map shall be created too\n" "See \\layer_map for details." ) + - gsi::method ("create_other_layers=", &db::LEFDEFReaderOptions::set_read_all_layers, + gsi::method ("create_other_layers=", &db::LEFDEFReaderOptions::set_read_all_layers, gsi::arg ("f"), "@brief Sets a value indicating whether layers not mapped in the layer map shall be created too\n" "See \\layer_map for details." ) + @@ -216,7 +216,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "This string can be either a layer number, a layer/datatype pair, a name or a combination of both. See \\LayerInfo for details." "The setter for this attribute is \\placement_blockage_layer=. See also \\produce_placement_blockages." ) + - gsi::method ("placement_blockage_layer=", &db::LEFDEFReaderOptions::set_placement_blockage_layer, + gsi::method ("placement_blockage_layer=", &db::LEFDEFReaderOptions::set_placement_blockage_layer, gsi::arg ("layer"), "@brief Sets the layer on which to produce the placement blockage.\n" "See \\placement_blockage_layer for details.\n" ) + @@ -240,7 +240,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n" "The attribute has been introduced in version 0.27." ) + - gsi::method ("region_layer=", &db::LEFDEFReaderOptions::set_region_layer, + gsi::method ("region_layer=", &db::LEFDEFReaderOptions::set_region_layer, gsi::arg ("layer"), "@brief Sets the layer on which to produce the regions.\n" "See \\region_layer for details.\n" "\n" @@ -312,7 +312,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n\n" "Mask specific rules have been introduced in version 0.27." ) + - gsi::method ("via_geometry_datatype", &db::LEFDEFReaderOptions::via_geometry_datatype_per_mask, + gsi::method ("via_geometry_datatype", &db::LEFDEFReaderOptions::via_geometry_datatype_per_mask, gsi::arg ("mask"), "@brief Gets the via geometry layer datatype value per mask.\n" "See \\produce_via_geometry for details about this property.\n" "The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)." @@ -400,7 +400,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n\n" "Mask specific rules have been introduced in version 0.27." ) + - gsi::method ("pins_datatype", &db::LEFDEFReaderOptions::pins_datatype_per_mask, + gsi::method ("pins_datatype", &db::LEFDEFReaderOptions::pins_datatype_per_mask, gsi::arg ("mask"), "@brief Gets the pin geometry layer datatype value per mask.\n" "See \\produce_via_geometry for details about the layer production rules." "The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)." @@ -476,7 +476,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n\n" "Mask specific rules have been introduced in version 0.27." ) + - gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype_per_mask, + gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype_per_mask, gsi::arg ("mask"), "@brief Gets the LEF pin geometry layer datatype value per mask.\n" "See \\produce_via_geometry for details about the layer production rules." "The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)." @@ -564,7 +564,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n\n" "Mask specific rules have been introduced in version 0.27." ) + - gsi::method ("fills_datatype", &db::LEFDEFReaderOptions::fills_datatype_per_mask, + gsi::method ("fills_datatype", &db::LEFDEFReaderOptions::fills_datatype_per_mask, gsi::arg ("mask"), "@brief Gets the fill geometry layer datatype value per mask.\n" "See \\produce_via_geometry for details about the layer production rules." "The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)." @@ -712,7 +712,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n\n" "Mask specific rules have been introduced in version 0.27." ) + - gsi::method ("routing_datatype", &db::LEFDEFReaderOptions::routing_datatype_per_mask, + gsi::method ("routing_datatype", &db::LEFDEFReaderOptions::routing_datatype_per_mask, gsi::arg ("mask"), "@brief Gets the routing geometry layer datatype value per mask.\n" "See \\produce_via_geometry for details about the layer production rules." "The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)." @@ -800,7 +800,7 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n\n" "Mask specific rules have been introduced in version 0.27." ) + - gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype_per_mask, + gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype_per_mask, gsi::arg ("mask"), "@brief Gets the special routing geometry layer datatype value per mask.\n" "See \\produce_via_geometry for details about the layer production rules." "The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)." @@ -885,11 +885,13 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "LEF macros. The \\macro_resolution_mode controls whether to use LEF geometry. If LEF geometry is not " "used, the DEF reader will look up macro cells from the \\macro_layouts and pull cell layouts from there.\n" "\n" - "The LEF cells are looked up by name from the macro layouts in the order these are given in this array.\n" + "The LEF cells are looked up as cells by name from the macro layouts in the order these are given in this array.\n" + "\n" + "\\macro_layout_files is another way of specifying such substitution layouts. This method accepts file names instead of layout objects.\n" "\n" "This property has been added in version 0.27.\n" ) + - gsi::method ("macro_layouts=", &db::LEFDEFReaderOptions::set_macro_layouts, + gsi::method ("macro_layouts=", &db::LEFDEFReaderOptions::set_macro_layouts, gsi::arg ("layouts"), "@brief Sets the layout objects used for resolving LEF macros in the DEF reader.\n" "See \\macro_layouts for more details about this property.\n" "\n" @@ -898,14 +900,33 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n" "This property has been added in version 0.27.\n" ) + + gsi::method ("macro_layout_files", &db::LEFDEFReaderOptions::macro_layout_files, + "@brief Gets the list of layout files to read for substituting macros in DEF\n" + "These files play the same role than the macro layouts (see \\macro_layouts), except that this property specifies a list of file names. " + "The given files are loaded automatically to resolve macro layouts instead of LEF geometry. See \\macro_resolution_mode for details when this happens. " + "Relative paths are resolved relative to the DEF file to read or relative to the technology base path.\n" + "Macros in need for substitution are looked up in the layout files by searching for cells with the same name. " + "The files are scanned in the order they are given in the file list.\n" + "The files from \\macro_layout_files are scanned after the layout objects specified with \\macro_layouts.\n" + "\n" + "The setter for this property is \\macro_layout_files=.\n" + "\n" + "This property has been added in version 0.27.1.\n" + ) + + gsi::method ("macro_layout_files=", &db::LEFDEFReaderOptions::set_macro_layout_files, gsi::arg ("file_paths"), + "@brief Sets the list of layout files to read for substituting macros in DEF\n" + "See \\macro_layout_files for details.\n" + "\n" + "This property has been added in version 0.27.1.\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. " - "Relative paths are resolved relative to the file to read.\n" + "Relative paths are resolved relative to the file to read or relative to the technology base path.\n" "\n" "The setter for this property is \\lef_files=." ) + - gsi::method ("lef_files=", &db::LEFDEFReaderOptions::set_lef_files, + gsi::method ("lef_files=", &db::LEFDEFReaderOptions::set_lef_files, gsi::arg ("lef_file_paths"), "@brief Sets the list technology LEF files to additionally import\n" "See \\lef_files for details." ) + diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index 43b5a4bcc..f999fa569 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -35,11 +35,11 @@ - 1 + 0 - LEF Files + LEF+Macro Files @@ -49,6 +49,69 @@ + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + LEF macro geometry + + + + + + + + Produce LEF geometry or use macro layout files for LEF FOREIGN + + + + + Always produce LEF geometry and ignore LEF FOREIGN + + + + + Always use macro layout files (assume LEF FOREIGN) + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + @@ -138,19 +201,18 @@ 6 - - - - Delete selected files + + + + Qt::Vertical - - ... + + + 20 + 0 + - - - :/clear.png:/clear.png - - + @@ -179,18 +241,19 @@ - - - - Qt::Vertical + + + + Delete selected files - - - 20 - 0 - + + ... - + + + :/clear.png:/clear.png + + @@ -226,6 +289,120 @@ + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Macro Layout Files +(used instead of LEF geometry if requested, resolution priority follows order) + + + + + + + + 0 + 0 + + + + QAbstractItemView::ExtendedSelection + + + + + + + Add LEF file + + + ... + + + + :/add.png:/add.png + + + + + + + Delete selected files + + + ... + + + + :/clear.png:/clear.png + + + + + + + Move selected files up + + + ... + + + + :/up.png:/up.png + + + + + + + Move selected files down + + + ... + + + + :/down.png:/down.png + + + + + + + Qt::Vertical + + + + 20 + 196 + + + + + + + @@ -248,30 +425,6 @@ 0 - - - - Layout DBU - - - - - - - - 0 - 0 - - - - - - - - Produce a parent cell per group - - - @@ -279,23 +432,6 @@ - - - - LEF import into DEF - - - - - - - - 0 - 0 - - - - @@ -316,7 +452,54 @@ - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Produce a parent cell per group + + + + + + + Layout DBU + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + QFrame::NoFrame @@ -340,38 +523,30 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Produce LEF geometry unless FOREIGN is used - - - - - Always produce LEF geometry and ignore FOREIGN - - - - - Never produce LEF geometry and assume FOREIGN always - - - - + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc index 9f5051c68..80668f1cb 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc @@ -131,68 +131,15 @@ public: if (! db::Technologies::instance ()->has_technology (tech_name)) { tech_name.clear (); // use default technology } + + db::LoadLayoutOptions options; const db::Technology *tech = db::Technologies::instance ()->technology_by_name (tech_name); - db::LEFDEFReaderOptions options; if (tech) { - const db::LEFDEFReaderOptions *tech_options = dynamic_cast(tech->load_layout_options ().get_options ("LEFDEF")); - if (tech_options) { - options = *tech_options; - } + options = tech->load_layout_options (); } - db::LEFDEFReaderState state (&options, *layout); - layout->dbu (options.dbu ()); - - if (import_lef) { - - tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Reading LEF file"))); - - db::LEFImporter importer; - - for (std::vector::const_iterator l = options.begin_lef_files (); l != options.end_lef_files (); ++l) { - tl::InputStream lef_stream (*l); - tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l; - importer.read (lef_stream, *layout, state); - } - - tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file; - importer.read (stream, *layout, state); - - } else { - - tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Reading DEF file"))); - - db::DEFImporter importer; - - QFileInfo def_fi (tl::to_qstring (data.file)); - - std::vector lef_files; - lef_files.insert (lef_files.end (), options.begin_lef_files (), options.end_lef_files ()); - lef_files.insert (lef_files.end (), data.lef_files.begin (), data.lef_files.end ()); - - for (std::vector::const_iterator l = lef_files.begin (); l != lef_files.end (); ++l) { - - QFileInfo fi (tl::to_qstring (*l)); - if (fi.isAbsolute ()) { - tl::InputStream lef_stream (*l); - tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l; - importer.read_lef (lef_stream, *layout, state); - } else { - std::string ex_l = tl::to_string (def_fi.absoluteDir ().absoluteFilePath (tl::to_qstring (*l))); - tl::InputStream lef_stream (ex_l); - tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l; - importer.read_lef (lef_stream, *layout, state); - } - - } - - tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file; - - importer.read (stream, *layout, state); - - } - - state.finish (*layout); + db::LEFDEFReader reader (stream); + reader.read_lefdef (*layout, options, import_lef); lay::LayoutView *view = lay::LayoutView::current (); if (! view || data.mode == 1) { diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index a13a216d9..58f35e1aa 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -364,6 +364,10 @@ 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 (add_macro_layout_file, SIGNAL (clicked ()), this, SLOT (add_macro_layout_file_clicked ())); + connect (del_macro_layout_files, SIGNAL (clicked ()), this, SLOT (del_macro_layout_files_clicked ())); + connect (move_macro_layout_files_up, SIGNAL (clicked ()), this, SLOT (move_macro_layout_files_up_clicked ())); + connect (move_macro_layout_files_down, SIGNAL (clicked ()), this, SLOT (move_macro_layout_files_down_clicked ())); connect (browse_mapfile, SIGNAL (clicked ()), this, SLOT (browse_mapfile_clicked ())); lay::activate_help_links (help_label); @@ -521,6 +525,11 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con for (int i = 0; i < lef_files->count (); ++i) { data->push_lef_file (tl::to_string (lef_files->item (i)->text ())); } + + data->clear_macro_layout_files (); + for (int i = 0; i < macro_layout_files->count (); ++i) { + data->push_macro_layout_file (tl::to_string (macro_layout_files->item (i)->text ())); + } } void @@ -597,6 +606,18 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options for (int i = 0; i < lef_files->count (); ++i) { lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); } + + macro_layout_files->clear (); + for (std::vector ::const_iterator f = data->begin_macro_layout_files (); f != data->end_macro_layout_files (); ++f) { + if (mp_tech) { + macro_layout_files->addItem (tl::to_qstring (mp_tech->correct_path (*f))); + } else { + macro_layout_files->addItem (tl::to_qstring (*f)); + } + } + for (int i = 0; i < macro_layout_files->count (); ++i) { + macro_layout_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + } } void @@ -657,114 +678,171 @@ LEFDEFReaderOptionsEditor::add_lef_file_clicked () } QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters)); - for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { - if (mp_tech) { - lef_files->addItem (tl::to_qstring (mp_tech->correct_path (tl::to_string (*f)))); - } else { - lef_files->addItem (*f); - } - } - for (int i = 0; i < lef_files->count (); ++i) { - lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); - } + add_files (lef_files, files, mp_tech.get ()); } void LEFDEFReaderOptionsEditor::del_lef_files_clicked () { - QStringList files; - for (int i = 0; i < lef_files->count (); ++i) { - if (! lef_files->item (i)->isSelected ()) { - files.push_back (lef_files->item (i)->text ()); - } - } - - lef_files->clear (); - for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { - lef_files->addItem (*f); - } - for (int i = 0; i < lef_files->count (); ++i) { - lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); - } + del_files (lef_files); } void LEFDEFReaderOptionsEditor::move_lef_files_up_clicked () { - std::set selected; - for (int i = 0; i < lef_files->count (); ++i) { - if (lef_files->item (i)->isSelected ()) { - selected.insert (lef_files->item (i)->text ()); - } - } - - QStringList files; - int j = -1; - for (int i = 0; i < lef_files->count (); ++i) { - if (lef_files->item (i)->isSelected ()) { - files.push_back (lef_files->item (i)->text ()); - } else { - if (j >= 0) { - files.push_back (lef_files->item (j)->text ()); - } - j = i; - } - } - if (j >= 0) { - files.push_back (lef_files->item (j)->text ()); - } - - lef_files->clear (); - for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { - lef_files->addItem (*f); - if (selected.find (*f) != selected.end ()) { - lef_files->item (lef_files->count () - 1)->setSelected (true); - } - } - for (int i = 0; i < lef_files->count (); ++i) { - lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); - } + move_files_up (lef_files); } void LEFDEFReaderOptionsEditor::move_lef_files_down_clicked () +{ + move_files_down (lef_files); +} + +void +LEFDEFReaderOptionsEditor::add_macro_layout_file_clicked () +{ + std::string title, filters; + title = tl::to_string (QObject::tr ("Add Macro Layout Files")); + filters = lay::MainWindow::instance ()->all_layout_file_formats (); + + std::string dir; + if (mp_tech) { + dir = mp_tech->base_path (); + } + + QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters)); + add_files (macro_layout_files, files, mp_tech.get ()); +} + +void +LEFDEFReaderOptionsEditor::del_macro_layout_files_clicked () +{ + del_files (macro_layout_files); +} + +void +LEFDEFReaderOptionsEditor::move_macro_layout_files_up_clicked () +{ + move_files_up (macro_layout_files); +} + +void +LEFDEFReaderOptionsEditor::move_macro_layout_files_down_clicked () +{ + move_files_down (macro_layout_files); +} + +void +LEFDEFReaderOptionsEditor::add_files (QListWidget *list, const QStringList &files, const db::Technology *tech) +{ + for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { + if (tech) { + list->addItem (tl::to_qstring (tech->correct_path (tl::to_string (*f)))); + } else { + list->addItem (*f); + } + } + for (int i = 0; i < list->count (); ++i) { + list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + } +} + +void +LEFDEFReaderOptionsEditor::del_files (QListWidget *list) +{ + QStringList files; + for (int i = 0; i < list->count (); ++i) { + if (! list->item (i)->isSelected ()) { + files.push_back (list->item (i)->text ()); + } + } + + list->clear (); + for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { + list->addItem (*f); + } + for (int i = 0; i < list->count (); ++i) { + list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + } +} + +void +LEFDEFReaderOptionsEditor::move_files_up (QListWidget *list) { std::set selected; - for (int i = 0; i < lef_files->count (); ++i) { - if (lef_files->item (i)->isSelected ()) { - selected.insert (lef_files->item (i)->text ()); + for (int i = 0; i < list->count (); ++i) { + if (list->item (i)->isSelected ()) { + selected.insert (list->item (i)->text ()); } } QStringList files; int j = -1; - for (int i = lef_files->count (); i > 0; ) { - --i; - if (lef_files->item (i)->isSelected ()) { - files.push_back (lef_files->item (i)->text ()); + for (int i = 0; i < list->count (); ++i) { + if (list->item (i)->isSelected ()) { + files.push_back (list->item (i)->text ()); } else { if (j >= 0) { - files.push_back (lef_files->item (j)->text ()); + files.push_back (list->item (j)->text ()); } j = i; } } if (j >= 0) { - files.push_back (lef_files->item (j)->text ()); + files.push_back (list->item (j)->text ()); } - lef_files->clear (); - for (QStringList::const_iterator f = files.end (); f != files.begin (); ) { - --f; - lef_files->addItem (*f); + list->clear (); + for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { + list->addItem (*f); if (selected.find (*f) != selected.end ()) { - lef_files->item (lef_files->count () - 1)->setSelected (true); + list->item (list->count () - 1)->setSelected (true); } } - for (int i = 0; i < lef_files->count (); ++i) { - lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + for (int i = 0; i < list->count (); ++i) { + list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + } +} + +void +LEFDEFReaderOptionsEditor::move_files_down (QListWidget *list) +{ + std::set selected; + for (int i = 0; i < list->count (); ++i) { + if (list->item (i)->isSelected ()) { + selected.insert (list->item (i)->text ()); + } + } + + QStringList files; + int j = -1; + for (int i = list->count (); i > 0; ) { + --i; + if (list->item (i)->isSelected ()) { + files.push_back (list->item (i)->text ()); + } else { + if (j >= 0) { + files.push_back (list->item (j)->text ()); + } + j = i; + } + } + if (j >= 0) { + files.push_back (list->item (j)->text ()); + } + + list->clear (); + for (QStringList::const_iterator f = files.end (); f != files.begin (); ) { + --f; + list->addItem (*f); + if (selected.find (*f) != selected.end ()) { + list->item (list->count () - 1)->setSelected (true); + } + } + for (int i = 0; i < list->count (); ++i) { + list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); } } } - diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h index cebd77047..8edfa9baf 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h @@ -98,10 +98,19 @@ private slots: void del_lef_files_clicked (); void move_lef_files_up_clicked (); void move_lef_files_down_clicked (); + void add_macro_layout_file_clicked (); + void del_macro_layout_files_clicked (); + void move_macro_layout_files_up_clicked (); + void move_macro_layout_files_down_clicked (); void browse_mapfile_clicked (); private: tl::weak_ptr mp_tech; + + static void add_files (QListWidget *list, const QStringList &files, const db::Technology *tech); + static void del_files (QListWidget *list); + static void move_files_up (QListWidget *list); + static void move_files_down (QListWidget *list); }; } diff --git a/testdata/ruby/dbReaders.rb b/testdata/ruby/dbReaders.rb index 8288d6c43..408a5b2d6 100644 --- a/testdata/ruby/dbReaders.rb +++ b/testdata/ruby/dbReaders.rb @@ -373,6 +373,10 @@ class DBReaders_TestClass < TestBase conf.lef_files = [ "u.lef", "v.lef" ] assert_equal(conf.lef_files.join(","), "u.lef,v.lef") + assert_equal(conf.macro_layout_files.join(","), "") + conf.macro_layout_files = [ "u.gds", "v.oas" ] + assert_equal(conf.macro_layout_files.join(","), "u.gds,v.oas") + assert_equal(conf.read_lef_with_def, true) conf.read_lef_with_def = false assert_equal(conf.read_lef_with_def, false)