mirror of https://github.com/KLayout/klayout.git
WIP: new technology management scheme, libraries can be tech specific, update of technology in layout updates library references
This commit is contained in:
parent
c087f37aa9
commit
78695f9c23
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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> ¶ms)
|
||||
{
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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", ®ister_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"
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> ¶meters)
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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> ¶meters);
|
||||
virtual void technology_changed (const std::string &);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ¶meters)
|
||||
{
|
||||
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> ¶meters)
|
||||
{
|
||||
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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 &);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
Loading…
Reference in New Issue