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.
This commit is contained in:
Matthias Koefferlein 2017-04-23 19:30:55 +02:00
parent 01e5c607fc
commit 1091ea6d5b
11 changed files with 161 additions and 57 deletions

View File

@ -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<db::Layout *, int> m_referrers;

View File

@ -110,11 +110,25 @@ Class<db::Library> 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,

View File

@ -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;

View File

@ -223,6 +223,7 @@ InstPropertiesPage::update ()
const db::Cell &def_cell = def_layout->cell (def_cell_index);
std::pair<db::Library *, db::cell_index_type> 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 ();

View File

@ -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<std::string, std::pair<std::string, QDateTime> > new_lib_files;
std::vector<std::string> paths = lay::Application::instance ()->klayout_path ();
// build a list of paths vs. technology
std::vector<std::pair<std::string, std::string> > paths;
std::vector<std::string> klayout_path = lay::Application::instance ()->klayout_path ();
for (std::vector<std::string>::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 <std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
for (std::vector <std::pair<std::string, std::string> >::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<std::string, std::pair<std::string, QDateTime> >::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<std::string, std::pair<std::string, QDateTime> >::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<db::Library> 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<db::Library> 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 ();
}
}

View File

@ -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

View File

@ -28,6 +28,10 @@
<file alias="grain.xml">salt_templates/macro/grain.xml</file>
</qresource>
<qresource prefix="/salt_templates/macro/macros">
<file alias="new_macro.lym">salt_templates/macro/macros/new_macro.lym</file>
</qresource>
<qresource prefix="/salt_templates/macro/doc">
<file alias="readme.html">salt_templates/macro/doc/readme.html</file>
</qresource>
<!-- pymacro template -->

View File

@ -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;

View File

@ -4,7 +4,7 @@
<version>0.0</version>
<title>Ruby Macro</title>
<doc>This template provides a Ruby macro</doc>
<doc-url/>
<doc-url>doc/readme.html</doc-url>
<url/>
<license>GPLv3</license>
<author/>

View File

@ -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);

View File

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