WIP: new technology management scheme, libraries can be tech specific, update of technology in layout updates library references

This commit is contained in:
Matthias Koefferlein 2020-12-13 12:13:21 +01:00
parent c087f37aa9
commit 78695f9c23
29 changed files with 682 additions and 245 deletions

View File

@ -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<db::lib_id_type, db::lib_id_type> mapping;
std::set<db::lib_id_type> seen;
for (db::Layout::iterator c = begin (); c != end (); ++c) {
db::LibraryProxy *lib_proxy = dynamic_cast<db::LibraryProxy *> (&*c);
if (lib_proxy && seen.find (lib_proxy->lib_id ()) == seen.end ()) {
seen.insert (lib_proxy->lib_id ());
std::pair<bool, db::lib_id_type> 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<std::pair<db::LibraryProxy *, db::PCellVariant *> > pcells_to_map;
std::vector<db::LibraryProxy *> lib_cells_to_map;
for (db::Layout::iterator c = begin (); c != end (); ++c) {
std::map<db::lib_id_type, db::lib_id_type>::const_iterator m;
db::LibraryProxy *lib_proxy = dynamic_cast<db::LibraryProxy *> (&*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 <db::PCellVariant *> (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<std::pair<db::LibraryProxy *, db::PCellVariant *> >::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<bool, pcell_id_type> 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<std::string, tl::Variant> 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<db::LibraryProxy *>::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<bool, cell_index_type> 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 <std::string>:
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 <std::string>::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;
}

View File

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

View File

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

View File

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

View File

@ -66,14 +66,24 @@ LibraryManager::~LibraryManager ()
}
std::pair<bool, lib_id_type>
LibraryManager::lib_by_name (const std::string &name) const
LibraryManager::lib_by_name (const std::string &name, const std::set<std::string> &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<std::string>::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 ();

View File

@ -33,6 +33,7 @@
#include <map>
#include <vector>
#include <string>
#include <set>
namespace db
{
@ -50,7 +51,7 @@ class Library;
class DB_PUBLIC LibraryManager
{
public:
typedef std::map <std::string, lib_id_type> lib_name_map;
typedef std::multimap <std::string, lib_id_type> 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<bool, lib_id_type> lib_by_name (const std::string &name) const;
std::pair<bool, lib_id_type> lib_by_name (const std::string &name, const std::set<std::string> &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<bool, lib_id_type> lib_by_name (const std::string &name, const std::string &for_technology) const
{
std::set<std::string> 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<bool, lib_id_type> lib_by_name (const std::string &name) const
{
return lib_by_name (name, std::set<std::string> ());
}
/**
* @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<bool, lib_id_type> 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<std::string> &for_technologies) const
{
std::pair<bool, lib_id_type> 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
*

View File

@ -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:
/**

View File

@ -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<std::string, tl::Variant> &params)
{
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<db::Layout> 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"

View File

@ -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<std::string> library_names ()
@ -57,6 +62,15 @@ static std::vector<std::string> library_names ()
return r;
}
static std::vector<db::lib_id_type> library_ids ()
{
std::vector<db::lib_id_type> 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", &register_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"

View File

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

View File

@ -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<tl::Variant> pv;
@ -820,15 +837,14 @@ void
EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector <tl::Variant> &parameters)
{
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 <tl::Var
mp_pcell_parameters = 0;
mp_placeholder_label = 0;
if (pc.first && layout->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);

View File

@ -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 <tl::Variant> &parameters);
virtual void technology_changed (const std::string &);
};
}

View File

@ -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 &parameters)
{
mp_pcell_decl = pcell_decl;
mp_pcell_decl.reset (const_cast<db::PCellDeclaration *> (pcell_decl)); // no const weak_ptr ...
mp_layout = layout;
mp_view = view;
m_cv_index = cv_index;
@ -457,131 +457,136 @@ std::vector<tl::Variant>
PCellParametersPage::get_parameters (bool *ok)
{
std::vector<tl::Variant> parameters;
bool edit_error = true;
int r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<QLineEdit *> (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<QLineEdit *> (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<QLineEdit *> (m_widgets [r]);
if (le) {
parameters.back () = tl::Variant (tl::to_string (le->text ()));
}
}
break;
case db::PCellParameterDeclaration::t_list:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
std::vector<std::string> 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<lay::LayerSelectionComboBox *> (m_widgets [r]);
if (ly) {
parameters.back () = tl::Variant (ly->current_layer_props ());
}
}
break;
case db::PCellParameterDeclaration::t_boolean:
{
QCheckBox *cbx = dynamic_cast<QCheckBox *> (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<QComboBox*> (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<QLineEdit *> (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<QLineEdit *> (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<QLineEdit *> (m_widgets [r]);
if (le) {
parameters.back () = tl::Variant (tl::to_string (le->text ()));
}
}
break;
case db::PCellParameterDeclaration::t_list:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
std::vector<std::string> 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<lay::LayerSelectionComboBox *> (m_widgets [r]);
if (ly) {
parameters.back () = tl::Variant (ly->current_layer_props ());
}
}
break;
case db::PCellParameterDeclaration::t_boolean:
{
QCheckBox *cbx = dynamic_cast<QCheckBox *> (m_widgets [r]);
if (cbx) {
parameters.back () = tl::Variant (cbx->isChecked ());
}
}
break;
default:
break;
}
} else {
QComboBox *cb = dynamic_cast<QComboBox*> (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<tl::Variant> &parameters)
{
if (! mp_pcell_decl) {
return;
}
// write the changed value back
size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();

View File

@ -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<db::PCellDeclaration> mp_pcell_decl;
std::vector<QWidget *> m_widgets;
const db::Layout *mp_layout;
lay::LayoutView *mp_view;

View File

@ -75,7 +75,7 @@ void get_text_editor_options_pages (std::vector<lay::EditorOptionsPage *> &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<lay::EditorOptionsPage *> &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<lay::EditorOptionsPage *> &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 <class Svc>
@ -327,10 +327,10 @@ public:
return false;
}
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> &pages, lay::LayoutView * /*view*/, lay::Dispatcher *dispatcher) const
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> &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);
}

View File

@ -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<ConfigurationDescriptor>::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<std::vector<std::string> > &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) {

View File

@ -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 <class Iter>
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<ConfigurationDescriptor> m_cfg;
QTreeWidget *mp_tree_widget;
@ -107,6 +105,7 @@ private:
void set_stored_values (const std::list<std::vector<std::string> > &values) const;
void render_to (QTreeWidgetItem *item, int column, const std::vector<std::string> &values, RecentConfigurationPage::ConfigurationRendering rendering);
void layers_changed (int);
virtual void technology_changed (const std::string &);
};
}

View File

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

View File

@ -122,7 +122,7 @@ LibraryController::sync_files ()
m_file_watcher->enable (false);
}
std::map<std::string, std::pair<std::string, QDateTime> > new_lib_files;
std::map<std::string, LibInfo> new_lib_files;
// build a list of paths vs. technology
std::vector<std::pair<std::string, std::string> > paths;
@ -174,11 +174,11 @@ LibraryController::sync_files ()
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);
std::map<std::string, LibInfo>::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<db::Library> 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<std::string> new_names;
for (std::map<std::string, std::pair<std::string, QDateTime> >::const_iterator lf = new_lib_files.begin (); lf != new_lib_files.end (); ++lf) {
new_names.insert (lf->second.first);
for (std::map<std::string, LibInfo>::const_iterator lf = new_lib_files.begin (); lf != new_lib_files.end (); ++lf) {
new_names.insert (lf->second.name);
}
for (std::map<std::string, std::pair<std::string, QDateTime> >::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<std::string, LibInfo>::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<bool, db::lib_id_type> li = db::LibraryManager::instance ().lib_by_name (lf->second.first);
std::pair<bool, db::lib_id_type> 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));
}

View File

@ -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<std::string> tech;
};
tl::FileSystemWatcher *m_file_watcher;
tl::DeferredMethod<LibraryController> dm_sync_files;
std::map<std::string, std::pair<std::string, QDateTime> > m_lib_files;
std::map<std::string, LibInfo> m_lib_files;
void sync_files ();
};

View File

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

View File

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

View File

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

View File

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

View File

@ -25,6 +25,8 @@
#include "laybasicCommon.h"
#include "tlObject.h"
#include <QWidget>
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 ();
};
}

View File

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

View File

@ -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<db::MAGReaderOptions> ();
m_lambda = specific_options.lambda;

View File

@ -145,7 +145,7 @@ private:
std::map<std::string, std::string> 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);

View File

@ -122,7 +122,7 @@ MAGWriter::write_dummmy_top (const std::set<db::cell_index_type> &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 <std::pair <
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";