From 852f5c438b39adcc5ab4d6789cdebf9c14b77654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Fri, 5 Jun 2020 10:58:53 +0200 Subject: [PATCH] Implemented #560 (multiple technologies on libraries) (#576) * First implementation. * PORT BACK: fixed a few flaws (fixed-width side panel ..) 1. On "save as" the filename displayed in the cell view selection box was not updated 2. The width of the library and cellview panel could not be reduced below the width of the combo boxes in the headers. So the panels might have become pretty wide without being able to reduce them. * Implemented #560 (multiple techs on libraries) --- src/db/db/dbLibrary.cc | 33 ++ src/db/db/dbLibrary.h | 37 +- src/db/db/gsiDeclDbLibrary.cc | 45 +- src/edt/edt/EditorOptionsInst.ui | 386 +++++++++--------- src/edt/edt/InstPropertiesPage.ui | 108 ++++- src/lay/lay/layLibraryController.cc | 2 +- src/lay/lay/layTechSetupDialog.cc | 2 +- .../laybasic/layHierarchyControlPanel.cc | 1 + src/laybasic/laybasic/layLayoutView.cc | 2 + src/laybasic/laybasic/layLibrariesView.cc | 8 +- src/laybasic/laybasic/layWidgets.cc | 7 +- src/rba/unit_tests/rba.cc | 1 + testdata/ruby/dbLibrary.rb | 93 +++++ 13 files changed, 499 insertions(+), 226 deletions(-) create mode 100644 testdata/ruby/dbLibrary.rb diff --git a/src/db/db/dbLibrary.cc b/src/db/db/dbLibrary.cc index fec55c29b..6c0ca490c 100644 --- a/src/db/db/dbLibrary.cc +++ b/src/db/db/dbLibrary.cc @@ -46,6 +46,39 @@ Library::~Library () // .. nothing yet .. } +bool +Library::is_for_technology (const std::string &name) const +{ + return m_technologies.find (name) != m_technologies.end (); +} + +bool +Library::for_technologies () const +{ + return ! m_technologies.empty (); +} + +void +Library::set_technology (const std::string &t) +{ + m_technologies.clear (); + if (! t.empty ()) { + m_technologies.insert (t); + } +} + +void +Library::clear_technologies () +{ + m_technologies.clear (); +} + +void +Library::add_technology (const std::string &tech) +{ + m_technologies.insert (tech); +} + void Library::register_proxy (db::LibraryProxy *lib_proxy, db::Layout *ly) { diff --git a/src/db/db/dbLibrary.h b/src/db/db/dbLibrary.h index 422eec281..21cd70061 100644 --- a/src/db/db/dbLibrary.h +++ b/src/db/db/dbLibrary.h @@ -31,6 +31,7 @@ #include "tlObject.h" #include +#include namespace db { @@ -108,18 +109,38 @@ public: * 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 + const std::set &get_technologies () const { - return m_technology; + return m_technologies; } /** - * @brief Sets the technology name this library is associated with + * @brief Gets a value indicating whether this library is associated with the given technology */ - void set_technology (const std::string &t) - { - m_technology = t; - } + bool is_for_technology (const std::string &name) const; + + /** + * @brief Gets a value indicating whether the library is associated with any technology + */ + bool for_technologies () const; + + /** + * @brief Sets the technology name this library is associated with + * + * This will reset the list of technologies to this one. + * If the given technology string is empty, the list of technologies will be cleared. + */ + void set_technology (const std::string &t); + + /** + * @brief Clears the list of technologies this library is associated with + */ + void clear_technologies (); + + /** + * @brief Additionally associate the library with the given technology + */ + void add_technology (const std::string &tech); /** * @brief Getter for the description property @@ -198,7 +219,7 @@ public: private: std::string m_name; std::string m_description; - std::string m_technology; + std::set m_technologies; lib_id_type m_id; db::Layout m_layout; std::map m_referrers; diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc index fff5bea12..98f737d88 100644 --- a/src/db/db/gsiDeclDbLibrary.cc +++ b/src/db/db/gsiDeclDbLibrary.cc @@ -68,6 +68,16 @@ static void delete_lib (db::Library *lib) db::LibraryManager::instance ().delete_lib (lib); } +static std::string get_technology (db::Library *lib) +{ + const std::set &techs = lib->get_technologies (); + if (techs.empty ()) { + return std::string (); + } else { + return *techs.begin (); + } +} + Class decl_Library ("db", "Library", gsi::constructor ("new", &new_lib, "@brief Creates a new, empty library" @@ -111,18 +121,47 @@ Class decl_Library ("db", "Library", gsi::method ("description=", &db::Library::set_description, gsi::arg ("description"), "@brief Sets the libraries' description text\n" ) + - gsi::method ("technology", &db::Library::get_technology, + gsi::method_ext ("#technology", &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." + "This attribute has been introduced in version 0.25. In version 0.27 this attribute is deprecated as " + "a library can now be associated with multiple technologies." ) + gsi::method ("technology=", &db::Library::set_technology, gsi::arg ("technology"), "@brief sets the name of the technology the library is associated with\n" "\n" "See \\technology for details. " - "This attribute has been introduced in version 0.25." + "This attribute has been introduced in version 0.25. In version 0.27, a library can be associated with " + "multiple technologies and this method will revert the selection to a single one. Passing an empty string " + "is equivalent to \\clear_technologies." + ) + + gsi::method ("clear_technologies", &db::Library::clear_technologies, + "@brief Clears the list of technologies the library is associated with.\n" + "See also \\add_technology.\n" + "\n" + "This method has been introduced in version 0.27" + ) + + gsi::method ("add_technology", &db::Library::add_technology, gsi::arg ("tech"), + "@brief Additionally associates the library with the given technology.\n" + "See also \\clear_technologies.\n" + "\n" + "This method has been introduced in version 0.27" + ) + + gsi::method ("is_for_technology", &db::Library::is_for_technology, gsi::arg ("tech"), + "@brief Returns a value indicating whether the library is associated with the given technology.\n" + "This method has been introduced in version 0.27" + ) + + gsi::method ("for_technologies", &db::Library::for_technologies, + "@brief Returns a value indicating whether the library is associated with any technology.\n" + "The method is equivalent to checking whether the \\technologies list is empty.\n" + "\n" + "This method has been introduced in version 0.27" + ) + + gsi::method ("technologies", &db::Library::get_technologies, + "@brief Gets the list of technologies this library is associated with.\n" + "This method has been introduced in version 0.27" ) + 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" diff --git a/src/edt/edt/EditorOptionsInst.ui b/src/edt/edt/EditorOptionsInst.ui index 74a3eb7be..3cd38120a 100644 --- a/src/edt/edt/EditorOptionsInst.ui +++ b/src/edt/edt/EditorOptionsInst.ui @@ -1,7 +1,8 @@ - + + EditorOptionsInst - - + + 0 0 @@ -9,52 +10,66 @@ 574 - + Form - - - 9 - - + + 6 + + 9 + + + 9 + + + 9 + + + 9 + - - + + QFrame::NoFrame - + QFrame::Raised - - - 0 - - + + 6 + + 0 + + + 0 + + + 0 + + + 0 + - - - - 0 - 0 + + + 0 0 - + Cell - - - - 7 - 0 + + + 0 0 @@ -62,47 +77,41 @@ - - + + ... - - + + Library - - - - - - Qt::Horizontal + + + + 0 + 0 + - - - 40 - 20 - - - + - + Qt::Vertical - + QSizePolicy::Fixed - + 522 8 @@ -111,99 +120,111 @@ - - - - 7 - 7 + + + 0 1 - + 0 - - + + Geometry - - - 9 - - + + 6 + + 9 + + + 9 + + + 9 + + + 9 + - - + + Rotation / Scaling - - + + 9 - + + 9 + + + 9 + + + 9 + + 6 - - - - - 0 - 0 + + + + 0 0 - - - + + + Mirror - + mirror_cbx - - - + + + Scaling factor (magnification) - - - - - 0 - 0 + + + + 0 0 - - - + + + degree - - - + + + Rotation angle - - - + + + (at X-axis before rotation) @@ -212,182 +233,177 @@ - - - - 5 - 5 + + + 0 0 - + Array Instance - + true - - + + 9 - + + 9 + + + 9 + + + 9 + + 6 - - - + + + Column vector (x,y) - - - - - 0 - 0 + + + + 1 0 - - - + + + x = - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 0 - 0 + + + + 1 0 - - - + + + y = - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 0 - 0 + + + + 1 0 - - - + + + y = - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 0 - 0 + + + + 1 0 - - - + + + x = - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - + + + Row vector (x,y) - - - + + + Rows/Columns - - - + + + columns = - - - - - 0 - 0 + + + + 1 0 - - - + + + rows = - - - - - 0 - 0 + + + + 1 0 - - - + + + Warning: although row and column vectors can be arbitrary combination, some design systems only accept orthogonal (rectangular) arrays. - + true @@ -397,10 +413,10 @@ some design systems only accept orthogonal (rectangular) arrays. - + Qt::Vertical - + 20 40 @@ -410,26 +426,26 @@ some design systems only accept orthogonal (rectangular) arrays. - - + + PCell - - + + Place origin of cell - + Qt::Vertical - + 50 8 @@ -462,8 +478,6 @@ some design systems only accept orthogonal (rectangular) arrays. column_y_le place_origin_cb - - - + diff --git a/src/edt/edt/InstPropertiesPage.ui b/src/edt/edt/InstPropertiesPage.ui index 0c6eea4c2..ab2f59622 100644 --- a/src/edt/edt/InstPropertiesPage.ui +++ b/src/edt/edt/InstPropertiesPage.ui @@ -17,7 +17,16 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 @@ -32,7 +41,16 @@ 6 - + + 0 + + + 0 + + + 0 + + 0 @@ -84,7 +102,16 @@ 6 - + + 0 + + + 0 + + + 0 + + 0 @@ -119,20 +146,14 @@ - - - - - - Qt::Horizontal + + + + 0 + 0 + - - - 40 - 20 - - - + @@ -178,7 +199,16 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 @@ -190,7 +220,16 @@ QFrame::Raised - + + 0 + + + 0 + + + 0 + + 0 @@ -265,7 +304,16 @@ Position / Rotation / Scaling - + + 9 + + + 9 + + + 9 + + 9 @@ -393,7 +441,16 @@ true - + + 9 + + + 9 + + + 9 + + 9 @@ -629,7 +686,16 @@ some design systems only accept orthogonal (rectangular) arrays. 6 - + + 0 + + + 0 + + + 0 + + 0 diff --git a/src/lay/lay/layLibraryController.cc b/src/lay/lay/layLibraryController.cc index b9b304d37..c76f13667 100644 --- a/src/lay/lay/layLibraryController.cc +++ b/src/lay/lay/layLibraryController.cc @@ -205,7 +205,7 @@ LibraryController::sync_files () } } - tl::log << "Registering as '" << lib->get_name () << "' for tech '" << lib->get_technology () << "'"; + 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 ()))); db::LibraryManager::instance ().register_lib (lib.release ()); diff --git a/src/lay/lay/layTechSetupDialog.cc b/src/lay/lay/layTechSetupDialog.cc index e89396411..266c42cf6 100644 --- a/src/lay/lay/layTechSetupDialog.cc +++ b/src/lay/lay/layTechSetupDialog.cc @@ -135,7 +135,7 @@ TechBaseEditorPage::setup () for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) { const db::Library *lib = db::LibraryManager::instance ().lib (l->second); - if (lib->get_technology () == tech ()->name ()) { + if (lib->is_for_technology (tech ()->name ())) { std::string text = lib->get_name (); if (! lib->get_description ().empty ()) { text += " - " + lib->get_description (); diff --git a/src/laybasic/laybasic/layHierarchyControlPanel.cc b/src/laybasic/laybasic/layHierarchyControlPanel.cc index d983e5b64..5ca8186dc 100644 --- a/src/laybasic/laybasic/layHierarchyControlPanel.cc +++ b/src/laybasic/laybasic/layHierarchyControlPanel.cc @@ -213,6 +213,7 @@ HierarchyControlPanel::HierarchyControlPanel (lay::LayoutView *view, QWidget *pa mp_selector = new QComboBox (this); mp_selector->setObjectName (QString::fromUtf8 ("cellview_selection")); + mp_selector->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed); ly->addWidget (mp_selector); mp_search_frame = new QFrame (this); diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc index 099c84e63..44d534acf 100644 --- a/src/laybasic/laybasic/layLayoutView.cc +++ b/src/laybasic/laybasic/layLayoutView.cc @@ -4739,6 +4739,8 @@ LayoutView::active_library_changed (int /*index*/) void LayoutView::cellview_changed (unsigned int index) { + mp_hierarchy_panel->do_update_content (index); + cellview_changed_event (index); if (m_title.empty ()) { diff --git a/src/laybasic/laybasic/layLibrariesView.cc b/src/laybasic/laybasic/layLibrariesView.cc index 3ef2bb4b6..5209b6f68 100644 --- a/src/laybasic/laybasic/layLibrariesView.cc +++ b/src/laybasic/laybasic/layLibrariesView.cc @@ -210,7 +210,8 @@ LibrariesView::LibrariesView (lay::LayoutView *view, QWidget *parent, const char ly->setContentsMargins (0, 0, 0, 0); mp_selector = new QComboBox (this); - mp_selector->setObjectName (QString::fromUtf8 ("cellview_selection")); + mp_selector->setObjectName (QString::fromUtf8 ("library_selection")); + mp_selector->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed); ly->addWidget (mp_selector); mp_search_frame = new QFrame (this); @@ -771,9 +772,10 @@ LibrariesView::display_string (int n) const if (! lib->get_description ().empty ()) { text += " - " + lib->get_description (); } - if (! lib->get_technology ().empty ()) { + if (lib->for_technologies ()) { text += " "; - text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ()))); + std::string tn = tl::join (std::vector (lib->get_technologies ().begin (), lib->get_technologies ().end ()), ","); + text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (tn))); } return text; } diff --git a/src/laybasic/laybasic/layWidgets.cc b/src/laybasic/laybasic/layWidgets.cc index 7c35f9734..aee5a598f 100644 --- a/src/laybasic/laybasic/layWidgets.cc +++ b/src/laybasic/laybasic/layWidgets.cc @@ -600,15 +600,16 @@ LibrarySelectionComboBox::update_list () 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 (! m_tech_set || lib->get_technology ().empty () || m_tech == lib->get_technology ()) { + if (! m_tech_set || !lib->for_technologies ()|| lib->is_for_technology (m_tech)) { 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 ()) { + if (m_tech_set && lib->for_technologies ()) { item_text += " "; - item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ()))); + std::string tn = tl::join (std::vector (lib->get_technologies ().begin (), lib->get_technologies ().end ()), ","); + item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (tn))); } addItem (tl::to_qstring (item_text), QVariant ((unsigned int) lib->get_id ())); diff --git a/src/rba/unit_tests/rba.cc b/src/rba/unit_tests/rba.cc index 924514fc9..af7cb5105 100644 --- a/src/rba/unit_tests/rba.cc +++ b/src/rba/unit_tests/rba.cc @@ -104,6 +104,7 @@ RUBYTEST (dbGlyphs, "dbGlyphs.rb") RUBYTEST (dbInstanceTest, "dbInstanceTest.rb") RUBYTEST (dbInstElementTest, "dbInstElementTest.rb") RUBYTEST (dbLayerMapping, "dbLayerMapping.rb") +RUBYTEST (dbLibrary, "dbLibrary.rb") RUBYTEST (dbLayout, "dbLayout.rb") RUBYTEST (dbLayoutTest, "dbLayoutTest.rb") RUBYTEST (dbLayoutDiff, "dbLayoutDiff.rb") diff --git a/testdata/ruby/dbLibrary.rb b/testdata/ruby/dbLibrary.rb new file mode 100644 index 000000000..cd73007a5 --- /dev/null +++ b/testdata/ruby/dbLibrary.rb @@ -0,0 +1,93 @@ +# encoding: UTF-8 + +# KLayout Layout Viewer +# Copyright (C) 2006-2020 Matthias Koefferlein +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +if !$:.member?(File::dirname($0)) + $:.push(File::dirname($0)) +end + +load("test_prologue.rb") + +class DBLibrary_TestClass < TestBase + + def test_1_registration + + lib = RBA::Library::new + + assert_equal(lib.name, "") + assert_equal(lib.id, 0) + + lib.register("RBA-unit-test") + + assert_equal(lib.name, "RBA-unit-test") + assert_equal(lib.id != 0, true) + + assert_equal(RBA::Library::library_names.member?("RBA-unit-test"), true) + assert_equal(RBA::Library::library_by_name("RBA-unit-test").id, lib.id) + + lib.delete + assert_equal(RBA::Library::library_by_name("RBA-unit-test"), nil) + + end + + def test_2_attributes + + lib = RBA::Library::new + + lib.description = "42 is the answer" + assert_equal(lib.description, "42 is the answer") + + assert_equal(lib.is_for_technology("X"), false) + assert_equal(lib.technologies, []) + assert_equal(lib.for_technologies, false) + + lib.technology = "X" + assert_equal(lib.is_for_technology("X"), true) + assert_equal(lib.technologies, ["X"]) + assert_equal(lib.for_technologies, true) + + lib.technology = "" + assert_equal(lib.is_for_technology("X"), false) + assert_equal(lib.technologies, []) + assert_equal(lib.for_technologies, false) + + lib.add_technology("Y") + assert_equal(lib.is_for_technology("X"), false) + assert_equal(lib.is_for_technology("Y"), true) + assert_equal(lib.technologies, ["Y"]) + assert_equal(lib.for_technologies, true) + + lib.clear_technologies + assert_equal(lib.is_for_technology("Y"), false) + assert_equal(lib.technologies, []) + assert_equal(lib.for_technologies, false) + + end + + def test_3_layout + + lib = RBA::Library::new + lib.layout.create_cell("X") + assert_equal(lib.layout.top_cell.name, "X") + + end + +end + +load("test_epilogue.rb") +