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 "dbLayout.h"
#include "dbMemStatistics.h" #include "dbMemStatistics.h"
#include "dbTrans.h" #include "dbTrans.h"
#include "dbTechnology.h"
#include "dbShapeRepository.h" #include "dbShapeRepository.h"
#include "dbPCellHeader.h" #include "dbPCellHeader.h"
#include "dbPCellVariant.h" #include "dbPCellVariant.h"
@ -442,6 +443,152 @@ Layout::operator= (const Layout &d)
return *this; 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 void
Layout::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const 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=")) { if (ex.test ("LIB=")) {
std::string lib_name = ex.skip (); 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) { if (! lib) {
return false; return false;
} }
@ -2284,7 +2431,7 @@ Layout::recover_proxy (std::vector <std::string>::const_iterator from, std::vect
if (ex.test ("LIB=")) { if (ex.test ("LIB=")) {
std::string lib_name = ex.skip (); 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) { if (! lib) {
return 0; return 0;
} }

View File

@ -67,6 +67,7 @@ class Region;
class Edges; class Edges;
class EdgePairs; class EdgePairs;
class Texts; class Texts;
class Technology;
class CellMapping; class CellMapping;
class LayerMapping; class LayerMapping;
@ -555,10 +556,29 @@ public:
} }
/** /**
* @brief Clear the layout * @brief Clears the layout
*/ */
void clear (); 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 * @brief Accessor to the array repository
*/ */
@ -1779,6 +1799,7 @@ private:
bool m_do_cleanup; bool m_do_cleanup;
bool m_editable; bool m_editable;
meta_info m_meta_info; meta_info m_meta_info;
std::string m_tech_name;
tl::Mutex m_lock; 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; 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) { if (! lib) {
throw tl::Exception (tl::to_string (tr ("Not a valid library name: ")) + libname); 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) { if (! pn.first) {
// substitute by static layout cell // substitute by static layout cell
// @@@ TODO: keep reference so we don't loose the connection immediately.
std::string name = r->first->cell_name (ci); std::string name = r->first->cell_name (ci);
db::Cell *old_cell = r->first->take_cell (ci); db::Cell *old_cell = r->first->take_cell (ci);
r->first->insert_cell (ci, name, new db::Cell (*old_cell)); 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) { if (! old_pcell_decl || ! new_pcell_decl) {
// substitute by static layout cell // substitute by static layout cell
// @@@ TODO: keep reference so we don't loose the connection immediately.
std::string name = r->first->cell_name (ci); std::string name = r->first->cell_name (ci);
db::Cell *old_cell = r->first->take_cell (ci); db::Cell *old_cell = r->first->take_cell (ci);
r->first->insert_cell (ci, name, new db::Cell (*old_cell)); r->first->insert_cell (ci, name, new db::Cell (*old_cell));
@ -233,6 +235,7 @@ Library::remap_to (db::Library *other)
if (! cn.first) { if (! cn.first) {
// unlink this proxy: substitute by static layout cell // 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); std::string name = r->first->cell_name (ci);
db::Cell *old_cell = r->first->take_cell (ci); db::Cell *old_cell = r->first->take_cell (ci);
r->first->insert_cell (ci, name, new db::Cell (*old_cell)); 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> 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); iterator l = m_lib_by_name.find (name);
if (l == m_lib_by_name.end ()) { while (l != m_lib_by_name.end () && l->first == name) {
return std::make_pair (false, lib_id_type (0)); bool found = true;
} else { for (std::set<std::string>::const_iterator t = for_technologies.begin (); t != for_technologies.end (); ++t) {
return std::make_pair (true, l->second); 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 void
@ -116,14 +126,28 @@ LibraryManager::register_lib (Library *library)
library->set_id (id); library->set_id (id);
// if the new library replaces the old one, remap existing library proxies before deleting the library // 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 ()); // (replacement is done only when all technologies are substituted)
if (ln != m_lib_by_name.end () && m_libs [ln->second]) { lib_name_map::iterator l = m_lib_by_name.find (library->get_name ());
m_libs [ln->second]->remap_to (library); bool found = false;
delete m_libs [ln->second]; while (l != m_lib_by_name.end () && l->first == library->get_name ()) {
m_libs [ln->second] = 0; 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 (); changed_event ();

View File

@ -33,6 +33,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <string> #include <string>
#include <set>
namespace db namespace db
{ {
@ -50,7 +51,7 @@ class Library;
class DB_PUBLIC LibraryManager class DB_PUBLIC LibraryManager
{ {
public: 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; 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. * @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 * @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 * @brief Register a library under the given name and associate a id
* *

View File

@ -29,6 +29,7 @@
#include "gsiObject.h" #include "gsiObject.h"
#include "dbLayout.h" #include "dbLayout.h"
#include "tlVariant.h" #include "tlVariant.h"
#include "tlObject.h"
namespace db namespace db
{ {
@ -327,7 +328,8 @@ public:
* @brief A declaration for a PCell * @brief A declaration for a PCell
*/ */
class DB_PUBLIC PCellDeclaration class DB_PUBLIC PCellDeclaration
: public gsi::ObjectBase : public gsi::ObjectBase,
public tl::Object
{ {
public: public:
/** /**

View File

@ -39,6 +39,7 @@
#include "dbLayoutUtils.h" #include "dbLayoutUtils.h"
#include "dbLayerMapping.h" #include "dbLayerMapping.h"
#include "dbCellMapping.h" #include "dbCellMapping.h"
#include "dbTechnology.h"
#include "tlStream.h" #include "tlStream.h"
namespace gsi 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) 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) { if (! lib) {
return 0; 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) 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) { if (! lib) {
return 0; return 0;
} }
@ -988,6 +989,21 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n" "\n"
"This method has been introduced in version 0.25." "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, gsi::method ("is_editable?", &db::Layout::is_editable,
"@brief Returns a value indicating whether the layout is editable.\n" "@brief Returns a value indicating whether the layout is editable.\n"
"@return True, if 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 (); 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 () static std::vector<std::string> library_names ()
@ -57,6 +62,15 @@ static std::vector<std::string> library_names ()
return r; 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) static void register_lib (db::Library *lib, const std::string &name)
{ {
lib->set_name (name); lib->set_name (name);
@ -110,22 +124,45 @@ LibraryClass decl_Library ("db", "Library",
gsi::constructor ("new", &new_lib, gsi::constructor ("new", &new_lib,
"@brief Creates a new, empty library" "@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" "@brief Gets a library by name\n"
"Returns the library object for the given name. If the name is not a valid\n" "Returns the library object for the given name. If the name is not a valid\n"
"library name, nil is returned.\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, gsi::method ("library_names", &library_names,
"@brief Returns a list of the names of all libraries registered in the system.\n" "@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"), gsi::method_ext ("register", &register_lib, gsi::arg ("name"),
"@brief Registers the library with the given name\n" "@brief Registers the library with the given name\n"
"\n" "\n"
"This method can be called in the constructor to register the library after \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" "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" "\n"
"This method will set the libraries' name.\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, gsi::method_ext ("delete", &delete_lib,
"@brief Deletes the library\n" "@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 implementation
EditorOptionsGeneric::EditorOptionsGeneric (lay::Dispatcher *dispatcher) EditorOptionsGeneric::EditorOptionsGeneric (lay::LayoutView *view, lay::Dispatcher *dispatcher)
: EditorOptionsPage (dispatcher) : EditorOptionsPage (view, dispatcher)
{ {
mp_ui = new Ui::EditorOptionsGeneric (); mp_ui = new Ui::EditorOptionsGeneric ();
mp_ui->setupUi (this); mp_ui->setupUi (this);
@ -206,8 +206,8 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root)
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// EditorOptionsText implementation // EditorOptionsText implementation
EditorOptionsText::EditorOptionsText (lay::Dispatcher *dispatcher) EditorOptionsText::EditorOptionsText (lay::LayoutView *view, lay::Dispatcher *dispatcher)
: lay::EditorOptionsPage (dispatcher) : lay::EditorOptionsPage (view, dispatcher)
{ {
mp_ui = new Ui::EditorOptionsText (); mp_ui = new Ui::EditorOptionsText ();
mp_ui->setupUi (this); mp_ui->setupUi (this);
@ -284,8 +284,8 @@ EditorOptionsText::setup (lay::Dispatcher *root)
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// EditorOptionsPath implementation // EditorOptionsPath implementation
EditorOptionsPath::EditorOptionsPath (lay::Dispatcher *dispatcher) EditorOptionsPath::EditorOptionsPath (lay::LayoutView *view, lay::Dispatcher *dispatcher)
: lay::EditorOptionsPage (dispatcher) : lay::EditorOptionsPage (view, dispatcher)
{ {
mp_ui = new Ui::EditorOptionsPath (); mp_ui = new Ui::EditorOptionsPath ();
mp_ui->setupUi (this); mp_ui->setupUi (this);
@ -385,8 +385,8 @@ EditorOptionsPath::setup (lay::Dispatcher *root)
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// EditorOptionsInst implementation // EditorOptionsInst implementation
EditorOptionsInst::EditorOptionsInst (lay::Dispatcher *dispatcher) EditorOptionsInst::EditorOptionsInst (lay::LayoutView *view, lay::Dispatcher *dispatcher)
: lay::EditorOptionsPage (dispatcher) : lay::EditorOptionsPage (view, dispatcher)
{ {
mp_ui = new Ui::EditorOptionsInst (); mp_ui = new Ui::EditorOptionsInst ();
mp_ui->setupUi (this); 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)); 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) EditorOptionsInst::setup (lay::Dispatcher *root)
{ {
m_cv_index = -1; m_cv_index = view ()->active_cellview_index ();
if (lay::LayoutView::current ()) {
m_cv_index = lay::LayoutView::current ()->active_cellview_index ();
}
try { try {
mp_ui->lib_cbx->blockSignals (true); mp_ui->lib_cbx->blockSignals (true);
std::string techname;
mp_ui->lib_cbx->update_list (); mp_ui->lib_cbx->update_list ();
if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) { 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 { } else {
mp_ui->lib_cbx->set_technology_filter (std::string (), false); mp_ui->lib_cbx->set_technology_filter (std::string (), false);
} }
@ -606,7 +620,7 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
// library // library
std::string l; std::string l;
root->config_get (cfg_edit_inst_lib_name, 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); mp_ui->lib_cbx->blockSignals (false);
update_cell_edits (); update_cell_edits ();
@ -667,8 +681,8 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// EditorOptionsInstPCellParam implementation // EditorOptionsInstPCellParam implementation
EditorOptionsInstPCellParam::EditorOptionsInstPCellParam (lay::Dispatcher *dispatcher) EditorOptionsInstPCellParam::EditorOptionsInstPCellParam (lay::LayoutView *view, lay::Dispatcher *dispatcher)
: lay::EditorOptionsPage (dispatcher), mp_pcell_parameters (0), mp_placeholder_label (0) : lay::EditorOptionsPage (view, dispatcher), mp_pcell_parameters (0), mp_placeholder_label (0)
{ {
mp_ui = new Ui::EditorOptionsInstPCellParam (); mp_ui = new Ui::EditorOptionsInstPCellParam ();
mp_ui->setupUi (this); mp_ui->setupUi (this);
@ -693,7 +707,7 @@ EditorOptionsInstPCellParam::apply (lay::Dispatcher *root)
std::string param; std::string param;
db::Layout *layout = 0; 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) { if (lib) {
layout = &lib->layout (); layout = &lib->layout ();
} else if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) { } 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 void
EditorOptionsInstPCellParam::setup (lay::Dispatcher *root) EditorOptionsInstPCellParam::setup (lay::Dispatcher *root)
{ {
m_cv_index = -1; m_cv_index = view ()->active_cellview_index ();
if (lay::LayoutView::current ()) {
m_cv_index = lay::LayoutView::current ()->active_cellview_index ();
}
bool needs_update = (mp_pcell_parameters == 0); bool needs_update = (mp_pcell_parameters == 0);
@ -743,7 +760,7 @@ EditorOptionsInstPCellParam::setup (lay::Dispatcher *root)
needs_update = true; 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 // pcell parameters
std::string param; std::string param;
@ -752,8 +769,8 @@ EditorOptionsInstPCellParam::setup (lay::Dispatcher *root)
db::Layout *layout = 0; db::Layout *layout = 0;
if (lib) { if (lib) {
layout = &lib->layout (); layout = &lib->layout ();
} else if (m_cv_index >= 0 && lay::LayoutView::current () && lay::LayoutView::current ()->cellview (m_cv_index).is_valid ()) { } else if (m_cv_index >= 0 && view ()->cellview (m_cv_index).is_valid ()) {
layout = &lay::LayoutView::current ()->cellview (m_cv_index)->layout (); layout = &view ()->cellview (m_cv_index)->layout ();
} }
std::vector<tl::Variant> pv; std::vector<tl::Variant> pv;
@ -820,15 +837,14 @@ void
EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector <tl::Variant> &parameters) EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector <tl::Variant> &parameters)
{ {
db::Layout *layout = 0; 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 // find the layout the cell has to be looked up: that is either the layout of the current instance or
// the library selected // 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) { if (lib) {
layout = &lib->layout (); layout = &lib->layout ();
} else if (view) { } else {
const lay::CellView &cv = view->cellview (m_cv_index); const lay::CellView &cv = view ()->cellview (m_cv_index);
if (cv.is_valid ()) { if (cv.is_valid ()) {
layout = &cv->layout (); layout = &cv->layout ();
} }
@ -856,10 +872,10 @@ EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector <tl::Var
mp_pcell_parameters = 0; mp_pcell_parameters = 0;
mp_placeholder_label = 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 = 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); this->layout ()->addWidget (mp_pcell_parameters);
mp_pcell_parameters->set_state (pcp_state); mp_pcell_parameters->set_state (pcp_state);

View File

@ -51,6 +51,7 @@ namespace lay
{ {
class PluginDeclaration; class PluginDeclaration;
class Dispatcher; class Dispatcher;
class LayoutView;
class Plugin; class Plugin;
} }
@ -68,7 +69,7 @@ class EditorOptionsGeneric
Q_OBJECT Q_OBJECT
public: public:
EditorOptionsGeneric (lay::Dispatcher *dispatcher); EditorOptionsGeneric (lay::LayoutView *view, lay::Dispatcher *dispatcher);
~EditorOptionsGeneric (); ~EditorOptionsGeneric ();
virtual std::string title () const; virtual std::string title () const;
@ -91,7 +92,7 @@ class EditorOptionsText
: public lay::EditorOptionsPage : public lay::EditorOptionsPage
{ {
public: public:
EditorOptionsText (lay::Dispatcher *dispatcher); EditorOptionsText (lay::LayoutView *view, lay::Dispatcher *dispatcher);
~EditorOptionsText (); ~EditorOptionsText ();
virtual std::string title () const; virtual std::string title () const;
@ -112,7 +113,7 @@ class EditorOptionsPath
Q_OBJECT Q_OBJECT
public: public:
EditorOptionsPath (lay::Dispatcher *dispatcher); EditorOptionsPath (lay::LayoutView *view, lay::Dispatcher *dispatcher);
~EditorOptionsPath (); ~EditorOptionsPath ();
virtual std::string title () const; virtual std::string title () const;
@ -136,7 +137,7 @@ class EditorOptionsInst
Q_OBJECT Q_OBJECT
public: public:
EditorOptionsInst (lay::Dispatcher *root); EditorOptionsInst (lay::LayoutView *view, lay::Dispatcher *root);
~EditorOptionsInst (); ~EditorOptionsInst ();
virtual std::string title () const; virtual std::string title () const;
@ -154,6 +155,9 @@ private:
Ui::EditorOptionsInst *mp_ui; Ui::EditorOptionsInst *mp_ui;
edt::PCellParametersPage *mp_pcell_parameters; edt::PCellParametersPage *mp_pcell_parameters;
int m_cv_index; int m_cv_index;
virtual void technology_changed (const std::string &);
virtual void active_cellview_changed ();
}; };
/** /**
@ -165,7 +169,7 @@ class EditorOptionsInstPCellParam
Q_OBJECT Q_OBJECT
public: public:
EditorOptionsInstPCellParam (lay::Dispatcher *root); EditorOptionsInstPCellParam (lay::LayoutView *view, lay::Dispatcher *root);
~EditorOptionsInstPCellParam (); ~EditorOptionsInstPCellParam ();
virtual std::string title () const; virtual std::string title () const;
@ -184,6 +188,7 @@ private:
std::string m_lib_name, m_cell_name; std::string m_lib_name, m_cell_name;
void update_pcell_parameters (const std::vector <tl::Variant> &parameters); 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 void
PCellParametersPage::init () PCellParametersPage::init ()
{ {
mp_pcell_decl = 0; mp_pcell_decl.reset (0);
mp_layout = 0; mp_layout = 0;
mp_view = 0; mp_view = 0;
m_cv_index = 0; m_cv_index = 0;
@ -185,7 +185,7 @@ PCellParametersPage::init ()
void void
PCellParametersPage::setup (const db::Layout *layout, lay::LayoutView *view, int cv_index, const db::PCellDeclaration *pcell_decl, const db::pcell_parameters_type &parameters) 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_layout = layout;
mp_view = view; mp_view = view;
m_cv_index = cv_index; m_cv_index = cv_index;
@ -457,131 +457,136 @@ std::vector<tl::Variant>
PCellParametersPage::get_parameters (bool *ok) PCellParametersPage::get_parameters (bool *ok)
{ {
std::vector<tl::Variant> parameters; std::vector<tl::Variant> parameters;
bool edit_error = true;
int r = 0; try {
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) {
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 ()) { bool edit_error = true;
parameters.push_back (m_parameters [r]);
} else {
parameters.push_back (p->get_default ());
}
} 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 ()) { if (r < (int) m_parameters.size ()) {
parameters.push_back (m_parameters [r]);
switch (p->get_type ()) { } else {
parameters.push_back (p->get_default ());
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 { } else {
QComboBox *cb = dynamic_cast<QComboBox*> (m_widgets [r]); parameters.push_back (tl::Variant ());
if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) {
parameters.back () = p->get_choices () [cb->currentIndex ()]; 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) { if (! edit_error) {
throw tl::Exception (tl::to_string (tr ("There are errors. See the highlighted edit fields for details."))); 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 void
PCellParametersPage::set_parameters (const std::vector<tl::Variant> &parameters) PCellParametersPage::set_parameters (const std::vector<tl::Variant> &parameters)
{ {
if (! mp_pcell_decl) {
return;
}
// write the changed value back // write the changed value back
size_t r = 0; size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations (); const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();

View File

@ -104,7 +104,7 @@ public:
*/ */
const db::PCellDeclaration *pcell_decl () const const db::PCellDeclaration *pcell_decl () const
{ {
return mp_pcell_decl; return mp_pcell_decl.get ();
} }
/** /**
@ -122,7 +122,7 @@ private:
QScrollArea *mp_parameters_area; QScrollArea *mp_parameters_area;
QLabel *mp_error_label; QLabel *mp_error_label;
QLabel *mp_error_icon; QLabel *mp_error_icon;
const db::PCellDeclaration *mp_pcell_decl; tl::weak_ptr<db::PCellDeclaration> mp_pcell_decl;
std::vector<QWidget *> m_widgets; std::vector<QWidget *> m_widgets;
const db::Layout *mp_layout; const db::Layout *mp_layout;
lay::LayoutView *mp_view; 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", 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])])); &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 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", 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])])); &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 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", 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])])); &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 EditorOptionsInstPCellParam (view, dispatcher));
ret.push_back (new EditorOptionsInst (dispatcher)); ret.push_back (new EditorOptionsInst (view, dispatcher));
} }
template <class Svc> template <class Svc>
@ -327,10 +327,10 @@ public:
return false; 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 // 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); pages.push_back (generic_opt);
} }

View File

@ -55,7 +55,7 @@ RecentConfigurationPage::init ()
ly->addWidget (mp_tree_widget); ly->addWidget (mp_tree_widget);
connect (mp_tree_widget, SIGNAL (itemClicked (QTreeWidgetItem *, int)), this, SLOT (item_clicked (QTreeWidgetItem *))); 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 ())); mp_tree_widget->setColumnCount (int (m_cfg.size ()));
@ -166,10 +166,10 @@ RecentConfigurationPage::render_to (QTreeWidgetItem *item, int column, const std
case RecentConfigurationPage::Layer: case RecentConfigurationPage::Layer:
{ {
int icon_size = mp_view->style ()->pixelMetric (QStyle::PM_ButtonIconSize); int icon_size = view ()->style ()->pixelMetric (QStyle::PM_ButtonIconSize);
lay::LayerPropertiesConstIterator l = lp_iter_from_string (mp_view, values [column]); lay::LayerPropertiesConstIterator l = lp_iter_from_string (view (), values [column]);
if (! l.is_null () && ! l.at_end ()) { 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])); item->setText (column, tl::to_qstring (values [column]));
} else { } else {
item->setIcon (column, QIcon ()); item->setIcon (column, QIcon ());
@ -219,7 +219,7 @@ RecentConfigurationPage::render_to (QTreeWidgetItem *item, int column, const std
const db::Library *lib = 0; const db::Library *lib = 0;
for (std::list<ConfigurationDescriptor>::const_iterator c = m_cfg.begin (); c != m_cfg.end (); ++c, ++libname_column) { for (std::list<ConfigurationDescriptor>::const_iterator c = m_cfg.begin (); c != m_cfg.end (); ++c, ++libname_column) {
if (c->rendering == RecentConfigurationPage::CellLibraryName) { 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; break;
} }
} }
@ -278,6 +278,12 @@ RecentConfigurationPage::layers_changed (int)
update_list (get_stored_values ()); update_list (get_stored_values ());
} }
void
RecentConfigurationPage::technology_changed (const std::string &)
{
update_list (get_stored_values ());
}
void void
RecentConfigurationPage::update_list (const std::list<std::vector<std::string> > &stored_values) 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); ex.read (cv_index);
} }
mp_view->set_or_request_current_layer (cv_index, lp); view ()->set_or_request_current_layer (cv_index, lp);
} else { } else {
dispatcher ()->config_set (c->cfg_name, v); dispatcher ()->config_set (c->cfg_name, v);
@ -349,11 +355,11 @@ RecentConfigurationPage::commit_recent (lay::Dispatcher *root)
std::string s; 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 (); int cv_index = view ()->current_layer ()->cellview_index ();
const lay::CellView &cv = mp_view->cellview (cv_index); const lay::CellView &cv = view ()->cellview (cv_index);
int li = mp_view->current_layer ()->layer_index (); int li = view ()->current_layer ()->layer_index ();
if (cv.is_valid () && cv->layout ().is_valid_layer (li)) { if (cv.is_valid () && cv->layout ().is_valid_layer (li)) {
s = cv->layout ().get_properties (li).to_string (); s = cv->layout ().get_properties (li).to_string ();
if (cv_index > 0) { if (cv_index > 0) {

View File

@ -46,8 +46,7 @@ class EditorOptionsPages;
* @brief The base class for a object properties page * @brief The base class for a object properties page
*/ */
class RecentConfigurationPage class RecentConfigurationPage
: public lay::EditorOptionsPage, : public lay::EditorOptionsPage
public tl::Object
{ {
Q_OBJECT Q_OBJECT
@ -79,7 +78,7 @@ public:
template <class Iter> template <class Iter>
RecentConfigurationPage (lay::LayoutView *view, lay::Dispatcher *dispatcher, const std::string &recent_cfg_name, Iter begin_cfg, Iter end_cfg) 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 (); init ();
} }
@ -96,7 +95,6 @@ private slots:
void item_clicked (QTreeWidgetItem *item); void item_clicked (QTreeWidgetItem *item);
private: private:
lay::LayoutView *mp_view;
std::string m_recent_cfg_name; std::string m_recent_cfg_name;
std::list<ConfigurationDescriptor> m_cfg; std::list<ConfigurationDescriptor> m_cfg;
QTreeWidget *mp_tree_widget; QTreeWidget *mp_tree_widget;
@ -107,6 +105,7 @@ private:
void set_stored_values (const std::list<std::vector<std::string> > &values) const; 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 render_to (QTreeWidgetItem *item, int column, const std::vector<std::string> &values, RecentConfigurationPage::ConfigurationRendering rendering);
void layers_changed (int); 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 (); 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 // find the layout the cell has to be looked up: that is either the layout of the current instance or
// the library selected // 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); 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 // find the layout the cell has to be looked up: that is either the layout of the current instance or
// the library selected // the library selected

View File

@ -122,7 +122,7 @@ LibraryController::sync_files ()
m_file_watcher->enable (false); 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 // build a list of paths vs. technology
std::vector<std::pair<std::string, std::string> > paths; std::vector<std::pair<std::string, std::string> > paths;
@ -174,11 +174,11 @@ LibraryController::sync_files ()
QFileInfo fi (tl::to_qstring (lib_path)); QFileInfo fi (tl::to_qstring (lib_path));
bool needs_load = false; 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 ()) { if (ll == m_lib_files.end ()) {
needs_load = true; needs_load = true;
} else { } else {
if (fi.lastModified () > ll->second.second) { if (fi.lastModified () > ll->second.time) {
needs_load = true; needs_load = true;
} else { } else {
new_lib_files.insert (*ll); new_lib_files.insert (*ll);
@ -189,7 +189,9 @@ LibraryController::sync_files ()
std::auto_ptr<db::Library> lib (new db::Library ()); std::auto_ptr<db::Library> lib (new db::Library ());
lib->set_description (filename); 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 ())); lib->set_name (tl::to_string (QFileInfo (*im).baseName ()));
tl::log << "Reading library '" << lib_path << "'"; tl::log << "Reading library '" << lib_path << "'";
@ -205,8 +207,19 @@ LibraryController::sync_files ()
} }
} }
tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'"; if (! p->second.empty ()) {
new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ()))); 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 ()); db::LibraryManager::instance ().register_lib (lib.release ());
@ -230,14 +243,14 @@ LibraryController::sync_files ()
std::set<std::string> new_names; 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) { for (std::map<std::string, LibInfo>::const_iterator lf = new_lib_files.begin (); lf != new_lib_files.end (); ++lf) {
new_names.insert (lf->second.first); 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) { 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.first) == new_names.end ()) { if (new_names.find (lf->second.name) == new_names.end ()) {
try { 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) { if (li.first) {
db::LibraryManager::instance ().delete_lib (db::LibraryManager::instance ().lib (li.second)); db::LibraryManager::instance ().delete_lib (db::LibraryManager::instance ().lib (li.second));
} }

View File

@ -119,9 +119,17 @@ private slots:
void sync_with_external_sources (); void sync_with_external_sources ();
private: private:
struct LibInfo
{
LibInfo () : name (), time (), tech () { }
std::string name;
QDateTime time;
std::set<std::string> tech;
};
tl::FileSystemWatcher *m_file_watcher; tl::FileSystemWatcher *m_file_watcher;
tl::DeferredMethod<LibraryController> dm_sync_files; 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 (); void sync_files ();
}; };

View File

@ -2506,7 +2506,7 @@ void
MainWindow::cm_new_layout () MainWindow::cm_new_layout ()
{ {
std::string technology = m_initial_technology; 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; static double s_new_cell_window_size = 2.0;
double dbu = 0.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 * const db::Technology *
LayoutHandle::technology () const 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) LayoutHandle::apply_technology (const std::string &tn)
{ {
set_tech_name (tn); set_tech_name (tn);
@ -223,15 +230,8 @@ LayoutHandle::apply_technology (const std::string &tn)
void void
LayoutHandle::set_tech_name (const std::string &tn) LayoutHandle::set_tech_name (const std::string &tn)
{ {
if (tn != m_tech_name) { if (mp_layout && tn != tech_name ()) {
if (db::Technologies::instance ()->has_technology (tn)) { mp_layout->set_technology_name (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));
}
technology_changed_event (); 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 there is no technology given and the reader reports one, use this one
if (technology.empty ()) { 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 ()) { if (! tech_from_reader.empty ()) {
set_tech_name (tech_from_reader); set_tech_name (tech_from_reader);
} }
@ -373,7 +373,7 @@ LayoutHandle::load ()
db::LayerMap new_lmap = reader.read (layout (), m_load_options); db::LayerMap new_lmap = reader.read (layout (), m_load_options);
// Attach the technology from the reader if it reports one // 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 ()) { if (! tech_from_reader.empty ()) {
set_tech_name (tech_from_reader); set_tech_name (tech_from_reader);
} }

View File

@ -115,10 +115,7 @@ public:
* *
* An empty name indicates the default technology should be used. * An empty name indicates the default technology should be used.
*/ */
const std::string &tech_name () const const std::string &tech_name () const;
{
return m_tech_name;
}
/** /**
* @brief Applies the given technology * @brief Applies the given technology
@ -300,7 +297,6 @@ private:
int m_ref_count; int m_ref_count;
std::string m_name; std::string m_name;
std::string m_filename; std::string m_filename;
std::string m_tech_name;
bool m_dirty; bool m_dirty;
db::SaveLayoutOptions m_save_options; db::SaveLayoutOptions m_save_options;
bool m_save_options_valid; bool m_save_options_valid;

View File

@ -24,6 +24,7 @@
#include "tlInternational.h" #include "tlInternational.h"
#include "layEditorOptionsPage.h" #include "layEditorOptionsPage.h"
#include "layEditorOptionsPages.h" #include "layEditorOptionsPages.h"
#include "layLayoutView.h"
namespace lay namespace lay
{ {
@ -31,10 +32,10 @@ namespace lay
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// EditorOptionsPage implementation // EditorOptionsPage implementation
EditorOptionsPage::EditorOptionsPage (lay::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) : QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (dispatcher), mp_view (view)
{ {
// nothing yet .. attach_events ();
} }
EditorOptionsPage::~EditorOptionsPage () EditorOptionsPage::~EditorOptionsPage ()
@ -42,6 +43,30 @@ EditorOptionsPage::~EditorOptionsPage ()
set_owner (0); 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 void
EditorOptionsPage::set_owner (EditorOptionsPages *owner) EditorOptionsPage::set_owner (EditorOptionsPages *owner)
{ {

View File

@ -25,6 +25,8 @@
#include "laybasicCommon.h" #include "laybasicCommon.h"
#include "tlObject.h"
#include <QWidget> #include <QWidget>
namespace lay namespace lay
@ -32,19 +34,21 @@ namespace lay
class PluginDeclaration; class PluginDeclaration;
class Dispatcher; class Dispatcher;
class LayoutView;
class Plugin; class Plugin;
class CellView;
class EditorOptionsPages; class EditorOptionsPages;
/** /**
* @brief The base class for a object properties page * @brief The base class for a object properties page
*/ */
class LAYBASIC_PUBLIC EditorOptionsPage class LAYBASIC_PUBLIC EditorOptionsPage
: public QWidget : public QWidget, public tl::Object
{ {
Q_OBJECT Q_OBJECT
public: public:
EditorOptionsPage (lay::Dispatcher *dispatcher); EditorOptionsPage (lay::LayoutView *view, lay::Dispatcher *dispatcher);
virtual ~EditorOptionsPage (); virtual ~EditorOptionsPage ();
virtual std::string title () const = 0; virtual std::string title () const = 0;
@ -72,11 +76,24 @@ protected:
return mp_dispatcher; return mp_dispatcher;
} }
lay::LayoutView *view () const
{
return mp_view;
}
virtual void active_cellview_changed () { }
virtual void technology_changed (const std::string & /*tech*/) { }
private: private:
EditorOptionsPages *mp_owner; EditorOptionsPages *mp_owner;
bool m_active; bool m_active;
const lay::PluginDeclaration *mp_plugin_declaration; const lay::PluginDeclaration *mp_plugin_declaration;
lay::Dispatcher *mp_dispatcher; 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 // if a technology is given and the file can be found in the technology's base path, take it
// from there. // from there.
std::string tn = layout.meta_info_value ("technology"); const db::Technology *tech = layout.technology ();
const db::Technology *tech = 0;
if (! tn.empty ()) {
tech = db::Technologies::instance ()->technology_by_name (tn);
}
if (tech && ! tech->base_path ().empty ()) { if (tech && ! tech->base_path ().empty ()) {
std::string new_fn = tl::combine_path (tech->base_path (), fn); 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 (); prepare_layers ();
mp_klayout_tech = 0; mp_klayout_tech = layout.technology ();
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);
}
const db::MAGReaderOptions &specific_options = options.get_options<db::MAGReaderOptions> (); const db::MAGReaderOptions &specific_options = options.get_options<db::MAGReaderOptions> ();
m_lambda = specific_options.lambda; m_lambda = specific_options.lambda;

View File

@ -145,7 +145,7 @@ private:
std::map<std::string, std::string> m_use_lib_paths; std::map<std::string, std::string> m_use_lib_paths;
db::VCplxTrans m_dbu_trans_inv; db::VCplxTrans m_dbu_trans_inv;
std::string m_tech; 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 (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); 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; std::string tech = m_options.tech;
if (tech.empty ()) { if (tech.empty ()) {
tech = layout.meta_info_value ("technology"); tech = layout.technology_name ();
} }
if (! tech.empty ()) { if (! tech.empty ()) {
os << "tech " << make_string (tl::to_lower_case (tech)) << "\n"; 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; std::string tech = m_options.tech;
if (tech.empty ()) { if (tech.empty ()) {
tech = layout.meta_info_value ("technology"); tech = layout.technology_name ();
} }
if (! tech.empty ()) { if (! tech.empty ()) {
os << "tech " << make_string (tl::to_lower_case (tech)) << "\n"; os << "tech " << make_string (tl::to_lower_case (tech)) << "\n";