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; }; /**