From 78695f9c233686d25558b53ee60a43ac2c50d6ee Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 13 Dec 2020 12:13:21 +0100 Subject: [PATCH] WIP: new technology management scheme, libraries can be tech specific, update of technology in layout updates library references --- src/db/db/dbLayout.cc | 151 +++++++++++- src/db/db/dbLayout.h | 23 +- src/db/db/dbLayoutContextHandler.cc | 2 +- src/db/db/dbLibrary.cc | 3 + src/db/db/dbLibraryManager.cc | 46 +++- src/db/db/dbLibraryManager.h | 67 ++++- src/db/db/dbPCellDeclaration.h | 4 +- src/db/db/gsiDeclDbLayout.cc | 20 +- src/db/db/gsiDeclDbLibrary.cc | 45 +++- src/db/unit_tests/dbLibrariesTests.cc | 40 +++ src/edt/edt/edtEditorOptionsPages.cc | 78 +++--- src/edt/edt/edtEditorOptionsPages.h | 15 +- src/edt/edt/edtPCellParametersPage.cc | 231 +++++++++--------- src/edt/edt/edtPCellParametersPage.h | 4 +- src/edt/edt/edtPlugin.cc | 12 +- src/edt/edt/edtRecentConfigurationPage.cc | 26 +- src/edt/edt/edtRecentConfigurationPage.h | 7 +- src/edt/edt/edtServiceImpl.cc | 4 +- src/lay/lay/layLibraryController.cc | 35 ++- src/lay/lay/layLibraryController.h | 10 +- src/lay/lay/layMainWindow.cc | 2 +- src/laybasic/laybasic/layCellView.cc | 26 +- src/laybasic/laybasic/layCellView.h | 6 +- src/laybasic/laybasic/layEditorOptionsPage.cc | 31 ++- src/laybasic/laybasic/layEditorOptionsPage.h | 21 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 6 +- .../streamers/magic/db_plugin/dbMAGReader.cc | 6 +- .../streamers/magic/db_plugin/dbMAGReader.h | 2 +- .../streamers/magic/db_plugin/dbMAGWriter.cc | 4 +- 29 files changed, 682 insertions(+), 245 deletions(-) diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index 2e767684e..e73be99d4 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -24,6 +24,7 @@ #include "dbLayout.h" #include "dbMemStatistics.h" #include "dbTrans.h" +#include "dbTechnology.h" #include "dbShapeRepository.h" #include "dbPCellHeader.h" #include "dbPCellVariant.h" @@ -442,6 +443,152 @@ Layout::operator= (const Layout &d) return *this; } +const db::Technology * +Layout::technology () const +{ + return db::Technologies::instance ()->technology_by_name (m_tech_name); +} + +void +Layout::set_technology_name (const std::string &tech) +{ + if (tech == m_tech_name) { + return; + } + + // determine which library to map to what + std::map mapping; + std::set seen; + + for (db::Layout::iterator c = begin (); c != end (); ++c) { + + db::LibraryProxy *lib_proxy = dynamic_cast (&*c); + if (lib_proxy && seen.find (lib_proxy->lib_id ()) == seen.end ()) { + + seen.insert (lib_proxy->lib_id ()); + + std::pair new_id (false, 0); + const db::Library *l = db::LibraryManager::instance ().lib (lib_proxy->lib_id ()); + if (l) { + new_id = db::LibraryManager::instance ().lib_by_name (l->get_name (), tech); + } + + if (new_id.first && new_id.second != l->get_id ()) { + mapping.insert (std::make_pair (l->get_id (), new_id.second)); + } + + } + + } + + if (mapping.empty ()) { + + bool needs_cleanup = false; + + std::vector > pcells_to_map; + std::vector lib_cells_to_map; + + for (db::Layout::iterator c = begin (); c != end (); ++c) { + + std::map::const_iterator m; + + db::LibraryProxy *lib_proxy = dynamic_cast (&*c); + if (lib_proxy && (m = mapping.find (lib_proxy->lib_id ())) != mapping.end ()) { + + db::Cell *lib_cell = &cell (lib_proxy->library_cell_index ()); + db::PCellVariant *lib_pcell = dynamic_cast (lib_cell); + if (lib_pcell) { + pcells_to_map.push_back (std::make_pair (lib_proxy, lib_pcell)); + } else { + lib_cells_to_map.push_back (lib_proxy); + } + + needs_cleanup = true; + + } + + } + + // We do PCell resolution before the library proxy resolution. The reason is that + // PCells may generate library proxies in their instantiation. Hence we must instantiate + // the PCells before we can resolve them. + for (std::vector >::const_iterator lp = pcells_to_map.begin (); lp != pcells_to_map.end (); ++lp) { + + db::cell_index_type ci = lp->first->Cell::cell_index (); + db::PCellVariant *lib_pcell = lp->second; + + std::pair pn = lib_pcell->layout ()->pcell_by_name (lp->first->get_basic_name ().c_str ()); + + if (! pn.first) { + + // substitute by static layout cell + // @@@ TODO: keep reference so we don't loose the connection immediately. + std::string name = cell_name (ci); + db::Cell *old_cell = take_cell (ci); + insert_cell (ci, name, new db::Cell (*old_cell)); + delete old_cell; + + } else { + + db::Library *new_lib = db::LibraryManager::instance ().lib (mapping [lp->first->lib_id ()]); + + const db::PCellDeclaration *old_pcell_decl = lib_pcell->layout ()->pcell_declaration (lib_pcell->pcell_id ()); + const db::PCellDeclaration *new_pcell_decl = new_lib->layout ().pcell_declaration (pn.second); + if (! old_pcell_decl || ! new_pcell_decl) { + + // substitute by static layout cell + // @@@ TODO: keep reference so we don't loose the connection immediately. + std::string name = cell_name (ci); + db::Cell *old_cell = take_cell (ci); + insert_cell (ci, name, new db::Cell (*old_cell)); + delete old_cell; + + } else { + + // map pcell parameters by name + std::map param_by_name = lib_pcell->parameters_by_name (); + lp->first->remap (new_lib->get_id (), new_lib->layout ().get_pcell_variant (pn.second, new_pcell_decl->map_parameters (param_by_name))); + + } + + } + + } + + for (std::vector::const_iterator lp = lib_cells_to_map.begin (); lp != lib_cells_to_map.end (); ++lp) { + + db::Library *new_lib = db::LibraryManager::instance ().lib (mapping [(*lp)->lib_id ()]); + + db::cell_index_type ci = (*lp)->Cell::cell_index (); + + std::pair cn = new_lib->layout ().cell_by_name ((*lp)->get_basic_name ().c_str ()); + + if (! cn.first) { + + // unlink this proxy: substitute by static layout cell + // @@@ TODO: keep reference so we don't loose the connection immediately. + std::string name = cell_name (ci); + db::Cell *old_cell = take_cell (ci); + insert_cell (ci, name, new db::Cell (*old_cell)); + delete old_cell; + + } else { + + (*lp)->remap (new_lib->get_id (), cn.second); + + } + + } + + if (needs_cleanup) { + cleanup (); + } + + } + + m_tech_name = tech; +} + void Layout::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const { @@ -2224,7 +2371,7 @@ Layout::recover_proxy_as (cell_index_type cell_index, std::vector : if (ex.test ("LIB=")) { std::string lib_name = ex.skip (); - Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (lib_name); + Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (lib_name, m_tech_name); if (! lib) { return false; } @@ -2284,7 +2431,7 @@ Layout::recover_proxy (std::vector ::const_iterator from, std::vect if (ex.test ("LIB=")) { std::string lib_name = ex.skip (); - Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (lib_name); + Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (lib_name, m_tech_name); if (! lib) { return 0; } diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index f1555cb61..c79629567 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -67,6 +67,7 @@ class Region; class Edges; class EdgePairs; class Texts; +class Technology; class CellMapping; class LayerMapping; @@ -555,10 +556,29 @@ public: } /** - * @brief Clear the layout + * @brief Clears the layout */ void clear (); + /** + * @brief Gets the technology name the layout is associated with + */ + const std::string &technology_name () const + { + return m_tech_name; + } + + /** + * @brief Gets the technology object the layout is associated with or null if no valid technology is associated + */ + const db::Technology *technology () const; + + /** + * @brief Changes the technology, the layout is associated with + * Changing the layout may re-assess all the library references as libraries can be technology specific + */ + void set_technology_name (const std::string &tech); + /** * @brief Accessor to the array repository */ @@ -1779,6 +1799,7 @@ private: bool m_do_cleanup; bool m_editable; meta_info m_meta_info; + std::string m_tech_name; tl::Mutex m_lock; /** diff --git a/src/db/db/dbLayoutContextHandler.cc b/src/db/db/dbLayoutContextHandler.cc index 5c6bf49fb..90cff6c50 100644 --- a/src/db/db/dbLayoutContextHandler.cc +++ b/src/db/db/dbLayoutContextHandler.cc @@ -80,7 +80,7 @@ tl::Variant LayoutContextHandler::eval_double_bracket (const std::string &s) con std::string tail = cp + 1; - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (libname); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (libname, mp_layout->technology_name ()); if (! lib) { throw tl::Exception (tl::to_string (tr ("Not a valid library name: ")) + libname); } diff --git a/src/db/db/dbLibrary.cc b/src/db/db/dbLibrary.cc index 0e10fe3e9..3103f0c56 100644 --- a/src/db/db/dbLibrary.cc +++ b/src/db/db/dbLibrary.cc @@ -192,6 +192,7 @@ Library::remap_to (db::Library *other) if (! pn.first) { // substitute by static layout cell + // @@@ TODO: keep reference so we don't loose the connection immediately. std::string name = r->first->cell_name (ci); db::Cell *old_cell = r->first->take_cell (ci); r->first->insert_cell (ci, name, new db::Cell (*old_cell)); @@ -204,6 +205,7 @@ Library::remap_to (db::Library *other) if (! old_pcell_decl || ! new_pcell_decl) { // substitute by static layout cell + // @@@ TODO: keep reference so we don't loose the connection immediately. std::string name = r->first->cell_name (ci); db::Cell *old_cell = r->first->take_cell (ci); r->first->insert_cell (ci, name, new db::Cell (*old_cell)); @@ -233,6 +235,7 @@ Library::remap_to (db::Library *other) if (! cn.first) { // unlink this proxy: substitute by static layout cell + // @@@ TODO: keep reference so we don't loose the connection immediately. std::string name = r->first->cell_name (ci); db::Cell *old_cell = r->first->take_cell (ci); r->first->insert_cell (ci, name, new db::Cell (*old_cell)); diff --git a/src/db/db/dbLibraryManager.cc b/src/db/db/dbLibraryManager.cc index ba8f2b685..8a8a0ff9e 100644 --- a/src/db/db/dbLibraryManager.cc +++ b/src/db/db/dbLibraryManager.cc @@ -66,14 +66,24 @@ LibraryManager::~LibraryManager () } std::pair -LibraryManager::lib_by_name (const std::string &name) const +LibraryManager::lib_by_name (const std::string &name, const std::set &for_technologies) const { iterator l = m_lib_by_name.find (name); - if (l == m_lib_by_name.end ()) { - return std::make_pair (false, lib_id_type (0)); - } else { - return std::make_pair (true, l->second); + while (l != m_lib_by_name.end () && l->first == name) { + bool found = true; + for (std::set::const_iterator t = for_technologies.begin (); t != for_technologies.end (); ++t) { + if (! lib (l->second)->is_for_technology (*t)) { + found = false; + break; + } + } + if (found) { + return std::make_pair (true, l->second); + } + ++l; } + + return std::make_pair (false, lib_id_type (0)); } void @@ -116,14 +126,28 @@ LibraryManager::register_lib (Library *library) library->set_id (id); // if the new library replaces the old one, remap existing library proxies before deleting the library - lib_name_map::iterator ln = m_lib_by_name.find (library->get_name ()); - if (ln != m_lib_by_name.end () && m_libs [ln->second]) { - m_libs [ln->second]->remap_to (library); - delete m_libs [ln->second]; - m_libs [ln->second] = 0; + // (replacement is done only when all technologies are substituted) + lib_name_map::iterator l = m_lib_by_name.find (library->get_name ()); + bool found = false; + while (l != m_lib_by_name.end () && l->first == library->get_name ()) { + if (m_libs [l->second] && m_libs [l->second]->get_technologies () == library->get_technologies ()) { + found = true; + break; + } + ++l; } - m_lib_by_name.insert (std::make_pair (library->get_name (), id)).first->second = id; + if (found) { + // substitute + m_libs [l->second]->remap_to (library); + delete m_libs [l->second]; + m_libs [l->second] = 0; + m_lib_by_name.erase (l); + } + + // insert new lib as first of this name + l = m_lib_by_name.find (library->get_name ()); + m_lib_by_name.insert (l, std::make_pair (library->get_name (), id)); changed_event (); diff --git a/src/db/db/dbLibraryManager.h b/src/db/db/dbLibraryManager.h index 48cf5e0a1..34d9e4428 100644 --- a/src/db/db/dbLibraryManager.h +++ b/src/db/db/dbLibraryManager.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace db { @@ -50,7 +51,7 @@ class Library; class DB_PUBLIC LibraryManager { public: - typedef std::map lib_name_map; + typedef std::multimap lib_name_map; typedef lib_name_map::const_iterator iterator; /** @@ -90,11 +91,41 @@ public: } /** - * @brief Get the library by name + * @brief Get the library by name which is valid for all given technologies + * + * This method looks up a library which is valid for all technologies listed in "for_technologies". It may be + * responsible for more than that too. * * @return A pair, the boolean is true, if the name is valid. The second member is the library id. */ - std::pair lib_by_name (const std::string &name) const; + std::pair lib_by_name (const std::string &name, const std::set &for_technologies) const; + + /** + * @brief Get the library by name which is valid for the given technology + * + * This method looks up a library which is valid for the given technology. It may be + * responsible for more than that too. + * + * @return A pair, the boolean is true, if the name is valid. The second member is the library id. + */ + std::pair lib_by_name (const std::string &name, const std::string &for_technology) const + { + std::set techs; + if (! for_technology.empty ()) { + techs.insert (for_technology); + } + return lib_by_name (name, techs); + } + + /** + * @brief Get the library by name for any technology + * + * @return A pair, the boolean is true, if the name is valid. The second member is the library id. + */ + std::pair lib_by_name (const std::string &name) const + { + return lib_by_name (name, std::set ()); + } /** * @brief Get the library by name @@ -111,6 +142,36 @@ public: } } + /** + * @brief Get the library by name and technology + * + * @return The pointer to the library or 0, if there is no library with that name. + */ + Library *lib_ptr_by_name (const std::string &name, const std::string &for_technology) const + { + std::pair ll = lib_by_name (name, for_technology); + if (ll.first) { + return lib (ll.second); + } else { + return 0; + } + } + + /** + * @brief Get the library by name and technology + * + * @return The pointer to the library or 0, if there is no library with that name. + */ + Library *lib_ptr_by_name (const std::string &name, const std::set &for_technologies) const + { + std::pair ll = lib_by_name (name, for_technologies); + if (ll.first) { + return lib (ll.second); + } else { + return 0; + } + } + /** * @brief Register a library under the given name and associate a id * diff --git a/src/db/db/dbPCellDeclaration.h b/src/db/db/dbPCellDeclaration.h index 540efa369..e27ad00b0 100644 --- a/src/db/db/dbPCellDeclaration.h +++ b/src/db/db/dbPCellDeclaration.h @@ -29,6 +29,7 @@ #include "gsiObject.h" #include "dbLayout.h" #include "tlVariant.h" +#include "tlObject.h" namespace db { @@ -327,7 +328,8 @@ public: * @brief A declaration for a PCell */ class DB_PUBLIC PCellDeclaration - : public gsi::ObjectBase + : public gsi::ObjectBase, + public tl::Object { public: /** diff --git a/src/db/db/gsiDeclDbLayout.cc b/src/db/db/gsiDeclDbLayout.cc index 2e85264b4..e9539343d 100644 --- a/src/db/db/gsiDeclDbLayout.cc +++ b/src/db/db/gsiDeclDbLayout.cc @@ -39,6 +39,7 @@ #include "dbLayoutUtils.h" #include "dbLayerMapping.h" #include "dbCellMapping.h" +#include "dbTechnology.h" #include "tlStream.h" namespace gsi @@ -750,7 +751,7 @@ static db::Cell *create_cell2 (db::Layout *layout, const std::string &name, cons static db::Cell *create_cell3 (db::Layout *layout, const std::string &name, const std::string &libname) { - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (libname); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (libname, layout->technology_name ()); if (! lib) { return 0; } @@ -765,7 +766,7 @@ static db::Cell *create_cell3 (db::Layout *layout, const std::string &name, cons static db::Cell *create_cell4 (db::Layout *layout, const std::string &name, const std::string &libname, const std::map ¶ms) { - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (libname); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (libname, layout->technology_name ()); if (! lib) { return 0; } @@ -988,6 +989,21 @@ Class decl_Layout ("db", "Layout", "\n" "This method has been introduced in version 0.25." ) + + gsi::method ("technology_name", &db::Layout::technology_name, + "@brief Gets the name of the technology this layout is associated with\n" + "This method has been introduced in version 0.27. Before that, the technology has been kept in the 'technology' meta data element." + ) + + gsi::method ("technology", &db::Layout::technology, + "@brief Gets the \\Technology object of the technology this layout is associated with or nil if the layout is not associated with a technology\n" + "This method has been introduced in version 0.27. Before that, the technology has been kept in the 'technology' meta data element." + ) + + gsi::method ("technology_name=", &db::Layout::set_technology_name, gsi::arg ("name"), + "@brief Sets the name of the technology this layout is associated with\n" + "Changing the technology name will re-assess all library references because libraries can be technology specified. " + "Cell layouts may be substituted during this re-assessment.\n" + "\n" + "This method has been introduced in version 0.27." + ) + gsi::method ("is_editable?", &db::Layout::is_editable, "@brief Returns a value indicating whether the layout is editable.\n" "@return True, if the layout is editable.\n" diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc index 0476a5087..a156b6375 100644 --- a/src/db/db/gsiDeclDbLibrary.cc +++ b/src/db/db/gsiDeclDbLibrary.cc @@ -43,9 +43,14 @@ static db::Library *new_lib () return new db::Library (); } -static db::Library *library_by_name (const std::string &name) +static db::Library *library_by_name (const std::string &name, const std::string &for_technology) { - return db::LibraryManager::instance ().lib_ptr_by_name (name); + return db::LibraryManager::instance ().lib_ptr_by_name (name, for_technology); +} + +static db::Library *library_by_id (db::lib_id_type id) +{ + return db::LibraryManager::instance ().lib (id); } static std::vector library_names () @@ -57,6 +62,15 @@ static std::vector library_names () return r; } +static std::vector library_ids () +{ + std::vector r; + for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) { + r.push_back (l->second); + } + return r; +} + static void register_lib (db::Library *lib, const std::string &name) { lib->set_name (name); @@ -110,22 +124,45 @@ LibraryClass decl_Library ("db", "Library", gsi::constructor ("new", &new_lib, "@brief Creates a new, empty library" ) + - gsi::method ("library_by_name", &library_by_name, gsi::arg ("name"), + gsi::method ("library_by_name", &library_by_name, gsi::arg ("name"), gsi::arg ("for_technology", std::string (), "unspecific"), "@brief Gets a library by name\n" "Returns the library object for the given name. If the name is not a valid\n" "library name, nil is returned.\n" + "\n" + "Different libraries can be registered under the same names for different technologies. When a technology name is given in 'for_technologies', " + "the first library matching this technology is returned. If no technology is given, the first library is returned.\n" + "\n" + "The technology selector has been introduced in version 0.27." + ) + + gsi::method ("library_by_id", &library_by_id, gsi::arg ("id"), + "@brief Gets the library object for the given ID\n" + "If the ID is not valid, nil is returned.\n" + "\n" + "This method has been introduced in version 0.27." ) + gsi::method ("library_names", &library_names, "@brief Returns a list of the names of all libraries registered in the system.\n" + "\n" + "NOTE: starting with version 0.27, the name of a library does not need to be unique if libraries are associated with specific technologies. " + "This method will only return the names and it's not possible not unambiguously derive the library object. It is recommended to use " + "\\library_ids and \\library_by_id to obtain the library unambiguously." + ) + + gsi::method ("library_ids", &library_ids, + "@brief Returns a list of valid library IDs.\n" + "See \\library_names for the reasoning behind this method." + "\n" + "This method has been introduced in version 0.27." ) + gsi::method_ext ("register", ®ister_lib, gsi::arg ("name"), "@brief Registers the library with the given name\n" "\n" "This method can be called in the constructor to register the library after \n" "the layout object has been filled with content. If a library with that name\n" - "already exists, it will be replaced with this library. \n" + "already exists for the same technologies, it will be replaced with this library. \n" "\n" "This method will set the libraries' name.\n" + "\n" + "The technology specific bahvior has been introduced in version 0.27." ) + gsi::method_ext ("delete", &delete_lib, "@brief Deletes the library\n" diff --git a/src/db/unit_tests/dbLibrariesTests.cc b/src/db/unit_tests/dbLibrariesTests.cc index 1be0d58f6..5e81a819c 100644 --- a/src/db/unit_tests/dbLibrariesTests.cc +++ b/src/db/unit_tests/dbLibrariesTests.cc @@ -617,3 +617,43 @@ TEST(3) } } +TEST(4) +{ + LIBT_A *lib_a1 = new LIBT_A (); + lib_a1->add_technology ("X"); + db::LibraryManager::instance ().register_lib (lib_a1); + + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A").second, lib_a1->get_id ()); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Z").first, false); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "").first, false); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "X").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "X").second, lib_a1->get_id ()); + + LIBT_A *lib_a2 = new LIBT_A (); + lib_a2->add_technology ("Y"); + db::LibraryManager::instance ().register_lib (lib_a2); + + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A").second, lib_a2->get_id ()); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Z").first, false); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "").first, false); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "X").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "X").second, lib_a1->get_id ()); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Y").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Y").second, lib_a2->get_id ()); + + LIBT_A *lib_a3 = new LIBT_A (); + lib_a3->add_technology ("X"); + db::LibraryManager::instance ().register_lib (lib_a3); + + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A").second, lib_a3->get_id ()); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Z").first, false); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "").first, false); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "X").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "X").second, lib_a3->get_id ()); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Y").first, true); + EXPECT_EQ (db::LibraryManager::instance ().lib_by_name ("A", "Y").second, lib_a2->get_id ()); +} + diff --git a/src/edt/edt/edtEditorOptionsPages.cc b/src/edt/edt/edtEditorOptionsPages.cc index 5cf86b819..b8c944587 100644 --- a/src/edt/edt/edtEditorOptionsPages.cc +++ b/src/edt/edt/edtEditorOptionsPages.cc @@ -69,8 +69,8 @@ static void configure_from_line_edit (lay::Dispatcher *dispatcher, QLineEdit *le // ------------------------------------------------------------------ // EditorOptionsGeneric implementation -EditorOptionsGeneric::EditorOptionsGeneric (lay::Dispatcher *dispatcher) - : EditorOptionsPage (dispatcher) +EditorOptionsGeneric::EditorOptionsGeneric (lay::LayoutView *view, lay::Dispatcher *dispatcher) + : EditorOptionsPage (view, dispatcher) { mp_ui = new Ui::EditorOptionsGeneric (); mp_ui->setupUi (this); @@ -206,8 +206,8 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root) // ------------------------------------------------------------------ // EditorOptionsText implementation -EditorOptionsText::EditorOptionsText (lay::Dispatcher *dispatcher) - : lay::EditorOptionsPage (dispatcher) +EditorOptionsText::EditorOptionsText (lay::LayoutView *view, lay::Dispatcher *dispatcher) + : lay::EditorOptionsPage (view, dispatcher) { mp_ui = new Ui::EditorOptionsText (); mp_ui->setupUi (this); @@ -284,8 +284,8 @@ EditorOptionsText::setup (lay::Dispatcher *root) // ------------------------------------------------------------------ // EditorOptionsPath implementation -EditorOptionsPath::EditorOptionsPath (lay::Dispatcher *dispatcher) - : lay::EditorOptionsPage (dispatcher) +EditorOptionsPath::EditorOptionsPath (lay::LayoutView *view, lay::Dispatcher *dispatcher) + : lay::EditorOptionsPage (view, dispatcher) { mp_ui = new Ui::EditorOptionsPath (); mp_ui->setupUi (this); @@ -385,8 +385,8 @@ EditorOptionsPath::setup (lay::Dispatcher *root) // ------------------------------------------------------------------ // EditorOptionsInst implementation -EditorOptionsInst::EditorOptionsInst (lay::Dispatcher *dispatcher) - : lay::EditorOptionsPage (dispatcher) +EditorOptionsInst::EditorOptionsInst (lay::LayoutView *view, lay::Dispatcher *dispatcher) + : lay::EditorOptionsPage (view, dispatcher) { mp_ui = new Ui::EditorOptionsInst (); mp_ui->setupUi (this); @@ -579,21 +579,35 @@ EditorOptionsInst::apply (lay::Dispatcher *root) root->config_set (cfg_edit_inst_place_origin, tl::to_string (place_origin)); } -void +void +EditorOptionsInst::technology_changed (const std::string &) +{ + // The layout's technology has changed + setup (dispatcher ()); +} + +void +EditorOptionsInst::active_cellview_changed () +{ + // The active cellview has changed + setup (dispatcher ()); +} + +void EditorOptionsInst::setup (lay::Dispatcher *root) { - m_cv_index = -1; - if (lay::LayoutView::current ()) { - m_cv_index = lay::LayoutView::current ()->active_cellview_index (); - } + m_cv_index = view ()->active_cellview_index (); try { mp_ui->lib_cbx->blockSignals (true); + std::string techname; + mp_ui->lib_cbx->update_list (); if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) { - mp_ui->lib_cbx->set_technology_filter (lay::LayoutView::current ()->cellview (m_cv_index)->tech_name (), true); + techname = lay::LayoutView::current ()->cellview (m_cv_index)->tech_name (); + mp_ui->lib_cbx->set_technology_filter (techname, true); } else { mp_ui->lib_cbx->set_technology_filter (std::string (), false); } @@ -606,7 +620,7 @@ EditorOptionsInst::setup (lay::Dispatcher *root) // library std::string l; root->config_get (cfg_edit_inst_lib_name, l); - mp_ui->lib_cbx->set_current_library (db::LibraryManager::instance ().lib_ptr_by_name (l)); + mp_ui->lib_cbx->set_current_library (db::LibraryManager::instance ().lib_ptr_by_name (l, techname)); mp_ui->lib_cbx->blockSignals (false); update_cell_edits (); @@ -667,8 +681,8 @@ EditorOptionsInst::setup (lay::Dispatcher *root) // ------------------------------------------------------------------ // EditorOptionsInstPCellParam implementation -EditorOptionsInstPCellParam::EditorOptionsInstPCellParam (lay::Dispatcher *dispatcher) - : lay::EditorOptionsPage (dispatcher), mp_pcell_parameters (0), mp_placeholder_label (0) +EditorOptionsInstPCellParam::EditorOptionsInstPCellParam (lay::LayoutView *view, lay::Dispatcher *dispatcher) + : lay::EditorOptionsPage (view, dispatcher), mp_pcell_parameters (0), mp_placeholder_label (0) { mp_ui = new Ui::EditorOptionsInstPCellParam (); mp_ui->setupUi (this); @@ -693,7 +707,7 @@ EditorOptionsInstPCellParam::apply (lay::Dispatcher *root) std::string param; db::Layout *layout = 0; - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name, view ()->active_cellview_ref ()->tech_name ()); if (lib) { layout = &lib->layout (); } else if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) { @@ -717,13 +731,16 @@ EditorOptionsInstPCellParam::apply (lay::Dispatcher *root) } } +void +EditorOptionsInstPCellParam::technology_changed (const std::string &) +{ + setup (dispatcher ()); +} + void EditorOptionsInstPCellParam::setup (lay::Dispatcher *root) { - m_cv_index = -1; - if (lay::LayoutView::current ()) { - m_cv_index = lay::LayoutView::current ()->active_cellview_index (); - } + m_cv_index = view ()->active_cellview_index (); bool needs_update = (mp_pcell_parameters == 0); @@ -743,7 +760,7 @@ EditorOptionsInstPCellParam::setup (lay::Dispatcher *root) needs_update = true; } - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name, view ()->active_cellview_ref ()->tech_name ()); // pcell parameters std::string param; @@ -752,8 +769,8 @@ EditorOptionsInstPCellParam::setup (lay::Dispatcher *root) db::Layout *layout = 0; if (lib) { layout = &lib->layout (); - } else if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) { - layout = &lay::LayoutView::current ()->cellview (m_cv_index)->layout (); + } else if (m_cv_index >= 0 && view ()->cellview (m_cv_index).is_valid ()) { + layout = &view ()->cellview (m_cv_index)->layout (); } std::vector pv; @@ -820,15 +837,14 @@ void EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector ¶meters) { db::Layout *layout = 0; - lay::LayoutView *view = lay::LayoutView::current (); // find the layout the cell has to be looked up: that is either the layout of the current instance or // the library selected - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name, view ()->active_cellview_ref ()->tech_name ()); if (lib) { layout = &lib->layout (); - } else if (view) { - const lay::CellView &cv = view->cellview (m_cv_index); + } else { + const lay::CellView &cv = view ()->cellview (m_cv_index); if (cv.is_valid ()) { layout = &cv->layout (); } @@ -856,10 +872,10 @@ EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector pcell_declaration (pc.second) && view && view->cellview (m_cv_index).is_valid ()) { + if (pc.first && layout->pcell_declaration (pc.second) && view ()->cellview (m_cv_index).is_valid ()) { mp_pcell_parameters = new PCellParametersPage (this, true /*dense*/); - mp_pcell_parameters->setup (&view->cellview (m_cv_index)->layout (), view, m_cv_index, layout->pcell_declaration (pc.second), parameters); + mp_pcell_parameters->setup (&view ()->cellview (m_cv_index)->layout (), view (), m_cv_index, layout->pcell_declaration (pc.second), parameters); this->layout ()->addWidget (mp_pcell_parameters); mp_pcell_parameters->set_state (pcp_state); diff --git a/src/edt/edt/edtEditorOptionsPages.h b/src/edt/edt/edtEditorOptionsPages.h index 3b639c5d8..92b697198 100644 --- a/src/edt/edt/edtEditorOptionsPages.h +++ b/src/edt/edt/edtEditorOptionsPages.h @@ -51,6 +51,7 @@ namespace lay { class PluginDeclaration; class Dispatcher; + class LayoutView; class Plugin; } @@ -68,7 +69,7 @@ class EditorOptionsGeneric Q_OBJECT public: - EditorOptionsGeneric (lay::Dispatcher *dispatcher); + EditorOptionsGeneric (lay::LayoutView *view, lay::Dispatcher *dispatcher); ~EditorOptionsGeneric (); virtual std::string title () const; @@ -91,7 +92,7 @@ class EditorOptionsText : public lay::EditorOptionsPage { public: - EditorOptionsText (lay::Dispatcher *dispatcher); + EditorOptionsText (lay::LayoutView *view, lay::Dispatcher *dispatcher); ~EditorOptionsText (); virtual std::string title () const; @@ -112,7 +113,7 @@ class EditorOptionsPath Q_OBJECT public: - EditorOptionsPath (lay::Dispatcher *dispatcher); + EditorOptionsPath (lay::LayoutView *view, lay::Dispatcher *dispatcher); ~EditorOptionsPath (); virtual std::string title () const; @@ -136,7 +137,7 @@ class EditorOptionsInst Q_OBJECT public: - EditorOptionsInst (lay::Dispatcher *root); + EditorOptionsInst (lay::LayoutView *view, lay::Dispatcher *root); ~EditorOptionsInst (); virtual std::string title () const; @@ -154,6 +155,9 @@ private: Ui::EditorOptionsInst *mp_ui; edt::PCellParametersPage *mp_pcell_parameters; int m_cv_index; + + virtual void technology_changed (const std::string &); + virtual void active_cellview_changed (); }; /** @@ -165,7 +169,7 @@ class EditorOptionsInstPCellParam Q_OBJECT public: - EditorOptionsInstPCellParam (lay::Dispatcher *root); + EditorOptionsInstPCellParam (lay::LayoutView *view, lay::Dispatcher *root); ~EditorOptionsInstPCellParam (); virtual std::string title () const; @@ -184,6 +188,7 @@ private: std::string m_lib_name, m_cell_name; void update_pcell_parameters (const std::vector ¶meters); + virtual void technology_changed (const std::string &); }; } diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc index 01b667002..5908c8d36 100644 --- a/src/edt/edt/edtPCellParametersPage.cc +++ b/src/edt/edt/edtPCellParametersPage.cc @@ -153,7 +153,7 @@ PCellParametersPage::PCellParametersPage (QWidget *parent, bool dense) void PCellParametersPage::init () { - mp_pcell_decl = 0; + mp_pcell_decl.reset (0); mp_layout = 0; mp_view = 0; m_cv_index = 0; @@ -185,7 +185,7 @@ PCellParametersPage::init () void PCellParametersPage::setup (const db::Layout *layout, lay::LayoutView *view, int cv_index, const db::PCellDeclaration *pcell_decl, const db::pcell_parameters_type ¶meters) { - mp_pcell_decl = pcell_decl; + mp_pcell_decl.reset (const_cast (pcell_decl)); // no const weak_ptr ... mp_layout = layout; mp_view = view; m_cv_index = cv_index; @@ -457,131 +457,136 @@ std::vector PCellParametersPage::get_parameters (bool *ok) { std::vector parameters; - bool edit_error = true; - int r = 0; - const std::vector &pcp = mp_pcell_decl->parameter_declarations (); - for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) { + try { - if (p->is_hidden () || p->get_type () == db::PCellParameterDeclaration::t_shape) { + if (! mp_pcell_decl) { + throw tl::Exception (tl::to_string (tr ("PCell no longer valid."))); + } - if (r < (int) m_parameters.size ()) { - parameters.push_back (m_parameters [r]); - } else { - parameters.push_back (p->get_default ()); - } + bool edit_error = true; - } else { + int r = 0; + const std::vector &pcp = mp_pcell_decl->parameter_declarations (); + for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) { - parameters.push_back (tl::Variant ()); + if (p->is_hidden () || p->get_type () == db::PCellParameterDeclaration::t_shape) { - if (p->get_choices ().empty ()) { - - switch (p->get_type ()) { - - case db::PCellParameterDeclaration::t_int: - { - QLineEdit *le = dynamic_cast (m_widgets [r]); - if (le) { - - try { - - int v = 0; - tl::from_string (tl::to_string (le->text ()), v); - - parameters.back () = tl::Variant (v); - lay::indicate_error (le, 0); - - } catch (tl::Exception &ex) { - - lay::indicate_error (le, &ex); - edit_error = false; - - } - - } - } - break; - - case db::PCellParameterDeclaration::t_double: - { - QLineEdit *le = dynamic_cast (m_widgets [r]); - if (le) { - - try { - - double v = 0; - tl::from_string (tl::to_string (le->text ()), v); - - parameters.back () = tl::Variant (v); - lay::indicate_error (le, 0); - - } catch (tl::Exception &ex) { - - lay::indicate_error (le, &ex); - edit_error = false; - - } - - } - } - break; - - case db::PCellParameterDeclaration::t_string: - { - QLineEdit *le = dynamic_cast (m_widgets [r]); - if (le) { - parameters.back () = tl::Variant (tl::to_string (le->text ())); - } - } - break; - - case db::PCellParameterDeclaration::t_list: - { - QLineEdit *le = dynamic_cast (m_widgets [r]); - if (le) { - std::vector values = tl::split (tl::to_string (le->text ()), ","); - parameters.back () = tl::Variant (values.begin (), values.end ()); - } - } - break; - - case db::PCellParameterDeclaration::t_layer: - { - lay::LayerSelectionComboBox *ly = dynamic_cast (m_widgets [r]); - if (ly) { - parameters.back () = tl::Variant (ly->current_layer_props ()); - } - } - break; - case db::PCellParameterDeclaration::t_boolean: - { - QCheckBox *cbx = dynamic_cast (m_widgets [r]); - if (cbx) { - parameters.back () = tl::Variant (cbx->isChecked ()); - } - } - break; - - default: - break; + if (r < (int) m_parameters.size ()) { + parameters.push_back (m_parameters [r]); + } else { + parameters.push_back (p->get_default ()); } } else { - QComboBox *cb = dynamic_cast (m_widgets [r]); - if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) { - parameters.back () = p->get_choices () [cb->currentIndex ()]; + parameters.push_back (tl::Variant ()); + + if (p->get_choices ().empty ()) { + + switch (p->get_type ()) { + + case db::PCellParameterDeclaration::t_int: + { + QLineEdit *le = dynamic_cast (m_widgets [r]); + if (le) { + + try { + + int v = 0; + tl::from_string (tl::to_string (le->text ()), v); + + parameters.back () = tl::Variant (v); + lay::indicate_error (le, 0); + + } catch (tl::Exception &ex) { + + lay::indicate_error (le, &ex); + edit_error = false; + + } + + } + } + break; + + case db::PCellParameterDeclaration::t_double: + { + QLineEdit *le = dynamic_cast (m_widgets [r]); + if (le) { + + try { + + double v = 0; + tl::from_string (tl::to_string (le->text ()), v); + + parameters.back () = tl::Variant (v); + lay::indicate_error (le, 0); + + } catch (tl::Exception &ex) { + + lay::indicate_error (le, &ex); + edit_error = false; + + } + + } + } + break; + + case db::PCellParameterDeclaration::t_string: + { + QLineEdit *le = dynamic_cast (m_widgets [r]); + if (le) { + parameters.back () = tl::Variant (tl::to_string (le->text ())); + } + } + break; + + case db::PCellParameterDeclaration::t_list: + { + QLineEdit *le = dynamic_cast (m_widgets [r]); + if (le) { + std::vector values = tl::split (tl::to_string (le->text ()), ","); + parameters.back () = tl::Variant (values.begin (), values.end ()); + } + } + break; + + case db::PCellParameterDeclaration::t_layer: + { + lay::LayerSelectionComboBox *ly = dynamic_cast (m_widgets [r]); + if (ly) { + parameters.back () = tl::Variant (ly->current_layer_props ()); + } + } + break; + case db::PCellParameterDeclaration::t_boolean: + { + QCheckBox *cbx = dynamic_cast (m_widgets [r]); + if (cbx) { + parameters.back () = tl::Variant (cbx->isChecked ()); + } + } + break; + + default: + break; + } + + } else { + + QComboBox *cb = dynamic_cast (m_widgets [r]); + if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) { + parameters.back () = p->get_choices () [cb->currentIndex ()]; + } + } } } - } - - try { - if (! edit_error) { throw tl::Exception (tl::to_string (tr ("There are errors. See the highlighted edit fields for details."))); } @@ -628,6 +633,10 @@ PCellParametersPage::get_parameters (bool *ok) void PCellParametersPage::set_parameters (const std::vector ¶meters) { + if (! mp_pcell_decl) { + return; + } + // write the changed value back size_t r = 0; const std::vector &pcp = mp_pcell_decl->parameter_declarations (); diff --git a/src/edt/edt/edtPCellParametersPage.h b/src/edt/edt/edtPCellParametersPage.h index 9786a2c8b..158a3cb07 100644 --- a/src/edt/edt/edtPCellParametersPage.h +++ b/src/edt/edt/edtPCellParametersPage.h @@ -104,7 +104,7 @@ public: */ const db::PCellDeclaration *pcell_decl () const { - return mp_pcell_decl; + return mp_pcell_decl.get (); } /** @@ -122,7 +122,7 @@ private: QScrollArea *mp_parameters_area; QLabel *mp_error_label; QLabel *mp_error_icon; - const db::PCellDeclaration *mp_pcell_decl; + tl::weak_ptr mp_pcell_decl; std::vector m_widgets; const db::Layout *mp_layout; lay::LayoutView *mp_view; diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc index 1cf07b535..8f7aa14c2 100644 --- a/src/edt/edt/edtPlugin.cc +++ b/src/edt/edt/edtPlugin.cc @@ -75,7 +75,7 @@ void get_text_editor_options_pages (std::vector &ret, ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-text-param", &text_cfg_descriptors[0], &text_cfg_descriptors[sizeof (text_cfg_descriptors) / sizeof (text_cfg_descriptors[0])])); - ret.push_back (new edt::EditorOptionsText (dispatcher)); + ret.push_back (new edt::EditorOptionsText (view, dispatcher)); } static @@ -101,7 +101,7 @@ void get_path_editor_options_pages (std::vector &ret, ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-path-param", &path_cfg_descriptors[0], &path_cfg_descriptors[sizeof (path_cfg_descriptors) / sizeof (path_cfg_descriptors[0])])); - ret.push_back (new EditorOptionsPath (dispatcher)); + ret.push_back (new EditorOptionsPath (view, dispatcher)); } static @@ -145,8 +145,8 @@ void get_inst_editor_options_pages (std::vector &ret, ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-inst-param", &inst_cfg_descriptors[0], &inst_cfg_descriptors[sizeof (inst_cfg_descriptors) / sizeof (inst_cfg_descriptors[0])])); - ret.push_back (new EditorOptionsInstPCellParam (dispatcher)); - ret.push_back (new EditorOptionsInst (dispatcher)); + ret.push_back (new EditorOptionsInstPCellParam (view, dispatcher)); + ret.push_back (new EditorOptionsInst (view, dispatcher)); } template @@ -327,10 +327,10 @@ public: return false; } - virtual void get_editor_options_pages (std::vector &pages, lay::LayoutView * /*view*/, lay::Dispatcher *dispatcher) const + virtual void get_editor_options_pages (std::vector &pages, lay::LayoutView *view, lay::Dispatcher *dispatcher) const { // NOTE: we do not set plugin_declaration which makes the page unspecific - EditorOptionsGeneric *generic_opt = new EditorOptionsGeneric (dispatcher); + EditorOptionsGeneric *generic_opt = new EditorOptionsGeneric (view, dispatcher); pages.push_back (generic_opt); } diff --git a/src/edt/edt/edtRecentConfigurationPage.cc b/src/edt/edt/edtRecentConfigurationPage.cc index 554f85be0..4c5726b8f 100644 --- a/src/edt/edt/edtRecentConfigurationPage.cc +++ b/src/edt/edt/edtRecentConfigurationPage.cc @@ -55,7 +55,7 @@ RecentConfigurationPage::init () ly->addWidget (mp_tree_widget); connect (mp_tree_widget, SIGNAL (itemClicked (QTreeWidgetItem *, int)), this, SLOT (item_clicked (QTreeWidgetItem *))); - mp_view->layer_list_changed_event.add (this, &RecentConfigurationPage::layers_changed); + view ()->layer_list_changed_event.add (this, &RecentConfigurationPage::layers_changed); mp_tree_widget->setColumnCount (int (m_cfg.size ())); @@ -166,10 +166,10 @@ RecentConfigurationPage::render_to (QTreeWidgetItem *item, int column, const std case RecentConfigurationPage::Layer: { - int icon_size = mp_view->style ()->pixelMetric (QStyle::PM_ButtonIconSize); - lay::LayerPropertiesConstIterator l = lp_iter_from_string (mp_view, values [column]); + int icon_size = view ()->style ()->pixelMetric (QStyle::PM_ButtonIconSize); + lay::LayerPropertiesConstIterator l = lp_iter_from_string (view (), values [column]); if (! l.is_null () && ! l.at_end ()) { - item->setIcon (column, lay::LayerTreeModel::icon_for_layer (l, mp_view, icon_size, icon_size, 0, true)); + item->setIcon (column, lay::LayerTreeModel::icon_for_layer (l, view (), icon_size, icon_size, 0, true)); item->setText (column, tl::to_qstring (values [column])); } else { item->setIcon (column, QIcon ()); @@ -219,7 +219,7 @@ RecentConfigurationPage::render_to (QTreeWidgetItem *item, int column, const std const db::Library *lib = 0; for (std::list::const_iterator c = m_cfg.begin (); c != m_cfg.end (); ++c, ++libname_column) { if (c->rendering == RecentConfigurationPage::CellLibraryName) { - lib = db::LibraryManager::instance ().lib_ptr_by_name (values [libname_column]); + lib = db::LibraryManager::instance ().lib_ptr_by_name (values [libname_column], view ()->active_cellview_ref ()->tech_name ()); break; } } @@ -278,6 +278,12 @@ RecentConfigurationPage::layers_changed (int) update_list (get_stored_values ()); } +void +RecentConfigurationPage::technology_changed (const std::string &) +{ + update_list (get_stored_values ()); +} + void RecentConfigurationPage::update_list (const std::list > &stored_values) { @@ -327,7 +333,7 @@ RecentConfigurationPage::item_clicked (QTreeWidgetItem *item) ex.read (cv_index); } - mp_view->set_or_request_current_layer (cv_index, lp); + view ()->set_or_request_current_layer (cv_index, lp); } else { dispatcher ()->config_set (c->cfg_name, v); @@ -349,11 +355,11 @@ RecentConfigurationPage::commit_recent (lay::Dispatcher *root) std::string s; - if (!(mp_view->current_layer ().is_null () || mp_view->current_layer ().at_end ()) && mp_view->current_layer ()->is_visual ()) { + if (!(view ()->current_layer ().is_null () || view ()->current_layer ().at_end ()) && view ()->current_layer ()->is_visual ()) { - int cv_index = mp_view->current_layer ()->cellview_index (); - const lay::CellView &cv = mp_view->cellview (cv_index); - int li = mp_view->current_layer ()->layer_index (); + int cv_index = view ()->current_layer ()->cellview_index (); + const lay::CellView &cv = view ()->cellview (cv_index); + int li = view ()->current_layer ()->layer_index (); if (cv.is_valid () && cv->layout ().is_valid_layer (li)) { s = cv->layout ().get_properties (li).to_string (); if (cv_index > 0) { diff --git a/src/edt/edt/edtRecentConfigurationPage.h b/src/edt/edt/edtRecentConfigurationPage.h index a177be7fb..56b542950 100644 --- a/src/edt/edt/edtRecentConfigurationPage.h +++ b/src/edt/edt/edtRecentConfigurationPage.h @@ -46,8 +46,7 @@ class EditorOptionsPages; * @brief The base class for a object properties page */ class RecentConfigurationPage - : public lay::EditorOptionsPage, - public tl::Object + : public lay::EditorOptionsPage { Q_OBJECT @@ -79,7 +78,7 @@ public: template RecentConfigurationPage (lay::LayoutView *view, lay::Dispatcher *dispatcher, const std::string &recent_cfg_name, Iter begin_cfg, Iter end_cfg) - : EditorOptionsPage (dispatcher), mp_view (view), m_recent_cfg_name (recent_cfg_name), m_cfg (begin_cfg, end_cfg) + : EditorOptionsPage (view, dispatcher), m_recent_cfg_name (recent_cfg_name), m_cfg (begin_cfg, end_cfg) { init (); } @@ -96,7 +95,6 @@ private slots: void item_clicked (QTreeWidgetItem *item); private: - lay::LayoutView *mp_view; std::string m_recent_cfg_name; std::list m_cfg; QTreeWidget *mp_tree_widget; @@ -107,6 +105,7 @@ private: void set_stored_values (const std::list > &values) const; void render_to (QTreeWidgetItem *item, int column, const std::vector &values, RecentConfigurationPage::ConfigurationRendering rendering); void layers_changed (int); + virtual void technology_changed (const std::string &); }; } diff --git a/src/edt/edt/edtServiceImpl.cc b/src/edt/edt/edtServiceImpl.cc index c15bc6106..8f9e048be 100644 --- a/src/edt/edt/edtServiceImpl.cc +++ b/src/edt/edt/edtServiceImpl.cc @@ -1414,7 +1414,7 @@ InstService::make_cell (const lay::CellView &cv) lay::LayerState layer_state = view ()->layer_snapshot (); - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name, cv->tech_name ()); // find the layout the cell has to be looked up: that is either the layout of the current instance or // the library selected @@ -1853,8 +1853,8 @@ InstService::switch_cell_or_pcell (bool switch_parameters) } - db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name); const lay::CellView &cv = view ()->cellview (m_cv_index); + db::Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (m_lib_name, cv->tech_name ()); // find the layout the cell has to be looked up: that is either the layout of the current instance or // the library selected diff --git a/src/lay/lay/layLibraryController.cc b/src/lay/lay/layLibraryController.cc index c76f13667..8b4dff669 100644 --- a/src/lay/lay/layLibraryController.cc +++ b/src/lay/lay/layLibraryController.cc @@ -122,7 +122,7 @@ LibraryController::sync_files () m_file_watcher->enable (false); } - std::map > new_lib_files; + std::map new_lib_files; // build a list of paths vs. technology std::vector > paths; @@ -174,11 +174,11 @@ LibraryController::sync_files () QFileInfo fi (tl::to_qstring (lib_path)); bool needs_load = false; - std::map >::iterator ll = m_lib_files.find (lib_path); + std::map::iterator ll = m_lib_files.find (lib_path); if (ll == m_lib_files.end ()) { needs_load = true; } else { - if (fi.lastModified () > ll->second.second) { + if (fi.lastModified () > ll->second.time) { needs_load = true; } else { new_lib_files.insert (*ll); @@ -189,7 +189,9 @@ LibraryController::sync_files () std::auto_ptr lib (new db::Library ()); lib->set_description (filename); - lib->set_technology (p->second); + if (! p->second.empty ()) { + lib->set_technology (p->second); + } lib->set_name (tl::to_string (QFileInfo (*im).baseName ())); tl::log << "Reading library '" << lib_path << "'"; @@ -205,8 +207,19 @@ LibraryController::sync_files () } } - tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'"; - new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ()))); + if (! p->second.empty ()) { + tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'"; + } else { + tl::log << "Registering as '" << lib->get_name () << "'"; + } + + LibInfo li; + li.name = lib->get_name (); + li.time = fi.lastModified (); + if (! p->second.empty ()) { + li.tech.insert (p->second); + } + new_lib_files.insert (std::make_pair (lib_path, li)); db::LibraryManager::instance ().register_lib (lib.release ()); @@ -230,14 +243,14 @@ LibraryController::sync_files () std::set new_names; - for (std::map >::const_iterator lf = new_lib_files.begin (); lf != new_lib_files.end (); ++lf) { - new_names.insert (lf->second.first); + for (std::map::const_iterator lf = new_lib_files.begin (); lf != new_lib_files.end (); ++lf) { + new_names.insert (lf->second.name); } - for (std::map >::const_iterator lf = m_lib_files.begin (); lf != m_lib_files.end (); ++lf) { - if (new_names.find (lf->second.first) == new_names.end ()) { + for (std::map::const_iterator lf = m_lib_files.begin (); lf != m_lib_files.end (); ++lf) { + if (new_names.find (lf->second.name) == new_names.end ()) { try { - std::pair li = db::LibraryManager::instance ().lib_by_name (lf->second.first); + std::pair li = db::LibraryManager::instance ().lib_by_name (lf->second.name, lf->second.tech); if (li.first) { db::LibraryManager::instance ().delete_lib (db::LibraryManager::instance ().lib (li.second)); } diff --git a/src/lay/lay/layLibraryController.h b/src/lay/lay/layLibraryController.h index 86c0bfdcd..e07f50ade 100644 --- a/src/lay/lay/layLibraryController.h +++ b/src/lay/lay/layLibraryController.h @@ -119,9 +119,17 @@ private slots: void sync_with_external_sources (); private: + struct LibInfo + { + LibInfo () : name (), time (), tech () { } + std::string name; + QDateTime time; + std::set tech; + }; + tl::FileSystemWatcher *m_file_watcher; tl::DeferredMethod dm_sync_files; - std::map > m_lib_files; + std::map m_lib_files; void sync_files (); }; diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 425f8485f..c0770ab1b 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2506,7 +2506,7 @@ void MainWindow::cm_new_layout () { std::string technology = m_initial_technology; - static std::string s_new_cell_cell_name; + static std::string s_new_cell_cell_name ("TOP"); static double s_new_cell_window_size = 2.0; double dbu = 0.0; diff --git a/src/laybasic/laybasic/layCellView.cc b/src/laybasic/laybasic/layCellView.cc index 0b28e12d0..e42317c43 100644 --- a/src/laybasic/laybasic/layCellView.cc +++ b/src/laybasic/laybasic/layCellView.cc @@ -206,13 +206,20 @@ LayoutHandle::remove_ref () } } +const std::string & +LayoutHandle::tech_name () const +{ + static std::string s_empty; + return mp_layout ? mp_layout->technology_name () : s_empty; +} + const db::Technology * LayoutHandle::technology () const { - return db::Technologies::instance ()->technology_by_name (m_tech_name); + return mp_layout ? mp_layout->technology () : 0; } -void +void LayoutHandle::apply_technology (const std::string &tn) { set_tech_name (tn); @@ -223,15 +230,8 @@ LayoutHandle::apply_technology (const std::string &tn) void LayoutHandle::set_tech_name (const std::string &tn) { - if (tn != m_tech_name) { - if (db::Technologies::instance ()->has_technology (tn)) { - m_tech_name = tn; - } else { - m_tech_name = std::string (); - } - if (mp_layout) { - mp_layout->add_meta_info (db::MetaInfo ("technology", tl::to_string (tr ("Technology name")), tn)); - } + if (mp_layout && tn != tech_name ()) { + mp_layout->set_technology_name (tn); technology_changed_event (); } } @@ -347,7 +347,7 @@ LayoutHandle::load (const db::LoadLayoutOptions &options, const std::string &tec // If there is no technology given and the reader reports one, use this one if (technology.empty ()) { - std::string tech_from_reader = layout ().meta_info_value ("technology"); + std::string tech_from_reader = layout ().technology_name (); if (! tech_from_reader.empty ()) { set_tech_name (tech_from_reader); } @@ -373,7 +373,7 @@ LayoutHandle::load () db::LayerMap new_lmap = reader.read (layout (), m_load_options); // Attach the technology from the reader if it reports one - std::string tech_from_reader = layout ().meta_info_value ("technology"); + std::string tech_from_reader = layout ().technology_name (); if (! tech_from_reader.empty ()) { set_tech_name (tech_from_reader); } diff --git a/src/laybasic/laybasic/layCellView.h b/src/laybasic/laybasic/layCellView.h index a1040dc6c..5f036b728 100644 --- a/src/laybasic/laybasic/layCellView.h +++ b/src/laybasic/laybasic/layCellView.h @@ -115,10 +115,7 @@ public: * * An empty name indicates the default technology should be used. */ - const std::string &tech_name () const - { - return m_tech_name; - } + const std::string &tech_name () const; /** * @brief Applies the given technology @@ -300,7 +297,6 @@ private: int m_ref_count; std::string m_name; std::string m_filename; - std::string m_tech_name; bool m_dirty; db::SaveLayoutOptions m_save_options; bool m_save_options_valid; diff --git a/src/laybasic/laybasic/layEditorOptionsPage.cc b/src/laybasic/laybasic/layEditorOptionsPage.cc index cc4a92d91..1d90960c6 100644 --- a/src/laybasic/laybasic/layEditorOptionsPage.cc +++ b/src/laybasic/laybasic/layEditorOptionsPage.cc @@ -24,6 +24,7 @@ #include "tlInternational.h" #include "layEditorOptionsPage.h" #include "layEditorOptionsPages.h" +#include "layLayoutView.h" namespace lay { @@ -31,10 +32,10 @@ namespace lay // ------------------------------------------------------------------ // EditorOptionsPage implementation -EditorOptionsPage::EditorOptionsPage (lay::Dispatcher *dispatcher) - : QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (dispatcher) +EditorOptionsPage::EditorOptionsPage (lay::LayoutView *view, lay::Dispatcher *dispatcher) + : QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (dispatcher), mp_view (view) { - // nothing yet .. + attach_events (); } EditorOptionsPage::~EditorOptionsPage () @@ -42,6 +43,30 @@ EditorOptionsPage::~EditorOptionsPage () set_owner (0); } +void +EditorOptionsPage::attach_events () +{ + detach_from_all_events (); + view ()->active_cellview_changed_event.add (this, &EditorOptionsPage::on_active_cellview_changed); + int cv_index = view ()->active_cellview_index (); + if (cv_index >= 0) { + view ()->cellview (cv_index)->technology_changed_event.add (this, &EditorOptionsPage::on_technology_changed); + } +} + +void +EditorOptionsPage::on_active_cellview_changed () +{ + active_cellview_changed (); + attach_events (); +} + +void +EditorOptionsPage::on_technology_changed () +{ + technology_changed (view ()->active_cellview_ref ()->tech_name ()); +} + void EditorOptionsPage::set_owner (EditorOptionsPages *owner) { diff --git a/src/laybasic/laybasic/layEditorOptionsPage.h b/src/laybasic/laybasic/layEditorOptionsPage.h index 3ee70b1a0..d6a6dad84 100644 --- a/src/laybasic/laybasic/layEditorOptionsPage.h +++ b/src/laybasic/laybasic/layEditorOptionsPage.h @@ -25,6 +25,8 @@ #include "laybasicCommon.h" +#include "tlObject.h" + #include namespace lay @@ -32,19 +34,21 @@ namespace lay class PluginDeclaration; class Dispatcher; +class LayoutView; class Plugin; +class CellView; class EditorOptionsPages; /** * @brief The base class for a object properties page */ class LAYBASIC_PUBLIC EditorOptionsPage - : public QWidget + : public QWidget, public tl::Object { Q_OBJECT public: - EditorOptionsPage (lay::Dispatcher *dispatcher); + EditorOptionsPage (lay::LayoutView *view, lay::Dispatcher *dispatcher); virtual ~EditorOptionsPage (); virtual std::string title () const = 0; @@ -72,11 +76,24 @@ protected: return mp_dispatcher; } + lay::LayoutView *view () const + { + return mp_view; + } + + virtual void active_cellview_changed () { } + virtual void technology_changed (const std::string & /*tech*/) { } + private: EditorOptionsPages *mp_owner; bool m_active; const lay::PluginDeclaration *mp_plugin_declaration; lay::Dispatcher *mp_dispatcher; + lay::LayoutView *mp_view; + + void on_active_cellview_changed (); + void on_technology_changed (); + void attach_events (); }; } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index c4628b38c..f8780418a 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -43,11 +43,7 @@ std::string correct_path (const std::string &fn, const db::Layout &layout, const // if a technology is given and the file can be found in the technology's base path, take it // from there. - std::string tn = layout.meta_info_value ("technology"); - const db::Technology *tech = 0; - if (! tn.empty ()) { - tech = db::Technologies::instance ()->technology_by_name (tn); - } + const db::Technology *tech = layout.technology (); if (tech && ! tech->base_path ().empty ()) { std::string new_fn = tl::combine_path (tech->base_path (), fn); diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc index f60be213e..fe7af4cb7 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc +++ b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc @@ -74,11 +74,7 @@ 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)) { - mp_klayout_tech = db::Technologies::instance ()->technology_by_name (klayout_tech_name); - } + mp_klayout_tech = layout.technology (); const db::MAGReaderOptions &specific_options = options.get_options (); m_lambda = specific_options.lambda; diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGReader.h b/src/plugins/streamers/magic/db_plugin/dbMAGReader.h index 8a5fb31a6..3d9d4ecf2 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGReader.h +++ b/src/plugins/streamers/magic/db_plugin/dbMAGReader.h @@ -145,7 +145,7 @@ private: std::map m_use_lib_paths; db::VCplxTrans m_dbu_trans_inv; std::string m_tech; - db::Technology *mp_klayout_tech; + const db::Technology *mp_klayout_tech; void do_read (db::Layout &layout, db::cell_index_type to_cell, tl::TextInputStream &stream); void do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl::TextInputStream &stream); diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc b/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc index 8c54b9f01..eb4b6a743 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc +++ b/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc @@ -122,7 +122,7 @@ MAGWriter::write_dummmy_top (const std::set &cell_set, cons std::string tech = m_options.tech; if (tech.empty ()) { - tech = layout.meta_info_value ("technology"); + tech = layout.technology_name (); } if (! tech.empty ()) { os << "tech " << make_string (tl::to_lower_case (tech)) << "\n"; @@ -177,7 +177,7 @@ MAGWriter::do_write_cell (db::cell_index_type ci, const std::vector