From 1091ea6d5b6dbb0a1ff350ba2a1a83da2dbce3f0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 23 Apr 2017 19:30:55 +0200 Subject: [PATCH] Technology specific libraries Libraries now carry a technology association and only libraries associated with the current technology can be selected. To enforce proper update, cancel() will be used upon change of technology. This avoids side effects when changing the technology without notifying the library selection widgets. The MainWindow::cancel method has been generalized to cover the functionality of cm_cancel without the exception handling. --- src/db/dbLibrary.h | 20 +++++ src/db/gsiDeclDbLibrary.cc | 18 ++++- src/edt/edtEditorOptionsPages.cc | 5 ++ src/edt/edtInstPropertiesPage.cc | 1 + src/lay/layLibraryController.cc | 107 +++++++++++++++---------- src/lay/layMainWindow.cc | 5 +- src/lay/laySaltTemplates.qrc | 4 + src/lay/layTechnologyController.cc | 5 ++ src/lay/salt_templates/macro/grain.xml | 2 +- src/laybasic/layWidgets.cc | 38 +++++++-- src/laybasic/layWidgets.h | 13 +++ 11 files changed, 161 insertions(+), 57 deletions(-) diff --git a/src/db/dbLibrary.h b/src/db/dbLibrary.h index 6819e7c36..3c2907123 100644 --- a/src/db/dbLibrary.h +++ b/src/db/dbLibrary.h @@ -101,6 +101,25 @@ public: m_name = name; } + /** + * @brief Gets the technology name this library is associated with + * + * If this attribute is non-empty, the library is selected only when the given technology is + * used for the layout. + */ + const std::string &get_technology () const + { + return m_technology; + } + + /** + * @brief Sets the technology name this library is associated with + */ + void set_technology (const std::string &t) + { + m_technology = t; + } + /** * @brief Getter for the description property */ @@ -153,6 +172,7 @@ public: private: std::string m_name; std::string m_description; + std::string m_technology; lib_id_type m_id; db::Layout m_layout; std::map m_referrers; diff --git a/src/db/gsiDeclDbLibrary.cc b/src/db/gsiDeclDbLibrary.cc index 64b357813..14f67a857 100644 --- a/src/db/gsiDeclDbLibrary.cc +++ b/src/db/gsiDeclDbLibrary.cc @@ -110,11 +110,25 @@ Class decl_Library ("Library", gsi::method ("description", &db::Library::get_description, "@brief Returns the libraries' description text\n" ) + - gsi::method ("description=", &db::Library::set_description, + gsi::method ("description=", &db::Library::set_description, "@brief Sets the libraries' description text\n" "@args description\n" ) + - gsi::method ("layout_const", (const db::Layout &(db::Library::*)() const) &db::Library::layout, + gsi::method ("technology", &db::Library::get_technology, + "@brief Returns name of the technology the library is associated with\n" + "If this attribute is a non-empty string, this library is only offered for " + "selection if the current layout uses this technology.\n" + "\n" + "This attribute has been introduced in version 0.25." + ) + + gsi::method ("technology=", &db::Library::set_technology, + "@brief sets the name of the technology the library is associated with\n" + "@args technology\n" + "\n" + "See \\technology for details. " + "This attribute has been introduced in version 0.25." + ) + + gsi::method ("layout_const", (const db::Layout &(db::Library::*)() const) &db::Library::layout, "@brief The layout object where the cells reside that this library defines (const version)\n" ) + gsi::method ("layout", (db::Layout &(db::Library::*)()) &db::Library::layout, diff --git a/src/edt/edtEditorOptionsPages.cc b/src/edt/edtEditorOptionsPages.cc index a0ac0308f..2e8fb8f9f 100644 --- a/src/edt/edtEditorOptionsPages.cc +++ b/src/edt/edtEditorOptionsPages.cc @@ -691,6 +691,11 @@ EditorOptionsInst::setup (lay::Plugin *root) m_cv_index = lay::LayoutView::current ()->active_cellview_index (); } 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); + } else { + mp_ui->lib_cbx->set_technology_filter (std::string (), false); + } // cell name std::string s; diff --git a/src/edt/edtInstPropertiesPage.cc b/src/edt/edtInstPropertiesPage.cc index 7bc7b1465..380d45063 100644 --- a/src/edt/edtInstPropertiesPage.cc +++ b/src/edt/edtInstPropertiesPage.cc @@ -223,6 +223,7 @@ InstPropertiesPage::update () const db::Cell &def_cell = def_layout->cell (def_cell_index); std::pair dl = def_layout->defining_library (def_cell_index); + lib_cbx->set_technology_filter (cv->tech_name (), true); lib_cbx->set_current_library (dl.first); if (dl.first) { def_layout = &dl.first->layout (); diff --git a/src/lay/layLibraryController.cc b/src/lay/layLibraryController.cc index 88334f7be..31906445c 100644 --- a/src/lay/layLibraryController.cc +++ b/src/lay/layLibraryController.cc @@ -21,6 +21,7 @@ */ #include "layLibraryController.h" +#include "layTechnology.h" #include "layApplication.h" #include "laySaltController.h" #include "layConfig.h" @@ -125,76 +126,96 @@ LibraryController::sync_files () std::map > new_lib_files; - std::vector paths = lay::Application::instance ()->klayout_path (); + // build a list of paths vs. technology + std::vector > paths; + + std::vector klayout_path = lay::Application::instance ()->klayout_path (); + for (std::vector::const_iterator p = klayout_path.begin (); p != klayout_path.end (); ++p) { + paths.push_back (std::make_pair (*p, std::string ())); + } // add the salt grains as potential sources for library definitions lay::SaltController *sc = lay::SaltController::instance (); if (sc) { for (lay::Salt::flat_iterator g = sc->salt ().begin_flat (); g != sc->salt ().end_flat (); ++g) { - paths.push_back ((*g)->path ()); + paths.push_back (std::make_pair ((*g)->path (), std::string ())); + } + } + + // add the technologies as potential sources for library definitions + + for (lay::Technologies::iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) { + if (! t->base_path ().empty ()) { + paths.push_back (std::make_pair (t->base_path (), t->name ())); } } // scan for libraries - for (std::vector ::const_iterator p = paths.begin (); p != paths.end (); ++p) { + for (std::vector >::const_iterator p = paths.begin (); p != paths.end (); ++p) { - QDir lp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("libraries")); - m_file_watcher->add_file (tl::to_string (lp.absolutePath ())); + QDir lp = QDir (tl::to_qstring (p->first)).filePath (tl::to_qstring ("libraries")); + if (lp.exists ()) { - QStringList name_filters; - name_filters << QString::fromUtf8 ("*"); + m_file_watcher->add_file (tl::to_string (lp.absolutePath ())); - QStringList libs = lp.entryList (name_filters, QDir::Files); - for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) { + QStringList name_filters; + name_filters << QString::fromUtf8 ("*"); - std::string filename = tl::to_string (*im); - std::string lib_path = tl::to_string (lp.absoluteFilePath (*im)); + QStringList libs = lp.entryList (name_filters, QDir::Files); + for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) { - try { + std::string filename = tl::to_string (*im); + std::string lib_path = tl::to_string (lp.absoluteFilePath (*im)); - QFileInfo fi (tl::to_qstring (lib_path)); + try { - bool needs_load = false; - 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) { + QFileInfo fi (tl::to_qstring (lib_path)); + + bool needs_load = false; + std::map >::iterator ll = m_lib_files.find (lib_path); + if (ll == m_lib_files.end ()) { needs_load = true; } else { - new_lib_files.insert (*ll); - } - } - - if (needs_load) { - - std::auto_ptr lib (new db::Library ()); - lib->set_description (filename); - lib->set_name (tl::to_string (QFileInfo (*im).baseName ())); - - tl::log << "Reading library '" << filename << "'"; - tl::InputStream stream (lib_path); - db::Reader reader (stream); - reader.read (lib->layout ()); - - // Use the libname if there is one - for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) { - if (m->name == "libname" && ! m->value.empty ()) { - lib->set_name (m->value); - break; + if (fi.lastModified () > ll->second.second) { + needs_load = true; + } else { + new_lib_files.insert (*ll); } } - new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ()))); + if (needs_load) { - db::LibraryManager::instance ().register_lib (lib.release ()); + std::auto_ptr lib (new db::Library ()); + lib->set_description (filename); + lib->set_technology (p->second); + lib->set_name (tl::to_string (QFileInfo (*im).baseName ())); + tl::log << "Reading library '" << lib_path << "'"; + tl::InputStream stream (lib_path); + db::Reader reader (stream); + reader.read (lib->layout ()); + + // Use the libname if there is one + for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) { + if (m->name == "libname" && ! m->value.empty ()) { + lib->set_name (m->value); + break; + } + } + + tl::log << "Registering as '" << lib->get_name () << "' for tech '" << lib->get_technology () << "'"; + new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ()))); + + db::LibraryManager::instance ().register_lib (lib.release ()); + + } + + } catch (tl::Exception &ex) { + tl::error << ex.msg (); } - } catch (tl::Exception &ex) { - tl::error << ex.msg (); } } diff --git a/src/lay/layMainWindow.cc b/src/lay/layMainWindow.cc index f94f059a1..6da478457 100644 --- a/src/lay/layMainWindow.cc +++ b/src/lay/layMainWindow.cc @@ -2608,7 +2608,6 @@ MainWindow::cm_cancel () { BEGIN_PROTECTED cancel (); - select_mode (lay::LayoutView::default_mode ()); END_PROTECTED } @@ -2618,8 +2617,6 @@ MainWindow::cm_cancel () void MainWindow::cancel () { - BEGIN_PROTECTED - // if any transaction is pending (this may happen when an operation threw an exception) // close transactions. if (m_manager.transacting ()) { @@ -2630,7 +2627,7 @@ MainWindow::cancel () (*vp)->cancel (); } - END_PROTECTED + select_mode (lay::LayoutView::default_mode ()); } void diff --git a/src/lay/laySaltTemplates.qrc b/src/lay/laySaltTemplates.qrc index e4155fe58..5eb43cde5 100644 --- a/src/lay/laySaltTemplates.qrc +++ b/src/lay/laySaltTemplates.qrc @@ -28,6 +28,10 @@ salt_templates/macro/grain.xml + salt_templates/macro/macros/new_macro.lym + + + salt_templates/macro/doc/readme.html diff --git a/src/lay/layTechnologyController.cc b/src/lay/layTechnologyController.cc index 1d0e1491d..94d6b0fec 100644 --- a/src/lay/layTechnologyController.cc +++ b/src/lay/layTechnologyController.cc @@ -269,6 +269,11 @@ TechnologyController::menu_activated (const std::string &symbol) const { if (symbol == "technology_selector:apply_technology") { if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview ().is_valid ()) { + // Cancels the current modes - changing the technology may make libraries unavailable + // for example. + if (mp_mw) { + mp_mw->cancel (); + } lay::LayoutView::current ()->active_cellview ()->apply_technology (m_current_technology); } return true; diff --git a/src/lay/salt_templates/macro/grain.xml b/src/lay/salt_templates/macro/grain.xml index ae9c5ffe2..8f69c4cd0 100644 --- a/src/lay/salt_templates/macro/grain.xml +++ b/src/lay/salt_templates/macro/grain.xml @@ -4,7 +4,7 @@ 0.0 Ruby Macro This template provides a Ruby macro - + doc/readme.html GPLv3 diff --git a/src/laybasic/layWidgets.cc b/src/laybasic/layWidgets.cc index 4b255e8a1..b1e7b2136 100644 --- a/src/laybasic/layWidgets.cc +++ b/src/laybasic/layWidgets.cc @@ -230,7 +230,8 @@ struct CellViewSelectionComboBoxPrivateData const lay::LayoutView *layout_view; }; -CellViewSelectionComboBox::CellViewSelectionComboBox (QWidget * /*parent*/) +CellViewSelectionComboBox::CellViewSelectionComboBox (QWidget *parent) + : QComboBox (parent) { mp_private = new CellViewSelectionComboBoxPrivateData (); mp_private->layout_view = 0; @@ -299,7 +300,8 @@ struct LayerSelectionComboBoxPrivateData int cv_index; }; -LayerSelectionComboBox::LayerSelectionComboBox (QWidget * /*parent*/) +LayerSelectionComboBox::LayerSelectionComboBox (QWidget *parent) + : QComboBox (parent) { mp_private = new LayerSelectionComboBoxPrivateData (); mp_private->no_layer_available = false; @@ -569,11 +571,22 @@ LayerSelectionComboBox::current_layer_props () const // ------------------------------------------------------------- // LibrarySelectionComboBox implementation -LibrarySelectionComboBox::LibrarySelectionComboBox (QWidget * /*parent*/) +LibrarySelectionComboBox::LibrarySelectionComboBox (QWidget *parent) + : QComboBox (parent), m_tech_set (false) { update_list (); } +void +LibrarySelectionComboBox::set_technology_filter (const std::string &tech, bool enabled) +{ + if (m_tech != tech || m_tech_set != enabled) { + m_tech = tech; + m_tech_set = enabled; + update_list (); + } +} + void LibrarySelectionComboBox::update_list () { @@ -585,12 +598,23 @@ LibrarySelectionComboBox::update_list () addItem (QObject::tr ("Local (no library)"), QVariant ()); for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) { + db::Library *lib = db::LibraryManager::instance ().lib (l->second); - if (! lib->get_description ().empty ()) { - addItem (tl::to_qstring (lib->get_name () + " - " + lib->get_description ()), QVariant ((unsigned int) lib->get_id ())); - } else { - addItem (tl::to_qstring (lib->get_name ()), QVariant ((unsigned int) lib->get_id ())); + if (! m_tech_set || lib->get_technology ().empty () || m_tech == lib->get_technology ()) { + + std::string item_text = lib->get_name (); + if (! lib->get_description ().empty ()) { + item_text += " - " + lib->get_description (); + } + if (m_tech_set && !lib->get_technology ().empty ()) { + item_text += " "; + item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ()))); + } + + addItem (tl::to_qstring (item_text), QVariant ((unsigned int) lib->get_id ())); + } + } set_current_library (lib); diff --git a/src/laybasic/layWidgets.h b/src/laybasic/layWidgets.h index 001a70a57..08019f82b 100644 --- a/src/laybasic/layWidgets.h +++ b/src/laybasic/layWidgets.h @@ -147,6 +147,19 @@ public: * @brief Update the list of libraries */ void update_list (); + + /** + * @brief Sets the technology filter + * + * If a technology filter is set, only the libraries associated with the given + * technology are shown. If enable is false, the technology name is ignored and + * all libraries are shown. + */ + void set_technology_filter (const std::string &tech, bool enable); + +private: + std::string m_tech; + bool m_tech_set; }; /**