WIP: cold references - keep reference information while libraries are not there or cells are missing.

This commit is contained in:
Matthias Koefferlein 2020-12-13 19:11:12 +01:00
parent fcf4fd74f6
commit ab36a660fb
9 changed files with 578 additions and 130 deletions

View File

@ -19,6 +19,7 @@ SOURCES = \
dbClipboard.cc \
dbClipboardData.cc \
dbClip.cc \
dbColdProxy.cc \
dbCommonReader.cc \
dbEdge.cc \
dbEdgePair.cc \
@ -214,6 +215,7 @@ HEADERS = \
dbClipboardData.h \
dbClipboard.h \
dbClip.h \
dbColdProxy.h \
dbCommonReader.h \
dbEdge.h \
dbEdgePair.h \

128
src/db/db/dbColdProxy.cc Normal file
View File

@ -0,0 +1,128 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbColdProxy.h"
#include "dbLibraryManager.h"
#include "dbLibrary.h"
#include "dbLayout.h"
#include "dbLayoutUtils.h"
#include "tlThreads.h"
namespace db
{
static tl::Mutex s_map_mutex;
static std::map<std::string, tl::weak_collection<ColdProxy> > s_proxies_per_library_name;
const tl::weak_collection<ColdProxy> &
ColdProxy::cold_proxies_per_lib_name (const std::string &libname)
{
tl::MutexLocker locker (&s_map_mutex);
std::map<std::string, tl::weak_collection<ColdProxy> >::const_iterator i = s_proxies_per_library_name.find (libname);
if (i != s_proxies_per_library_name.end ()) {
return i->second;
} else {
static tl::weak_collection<ColdProxy> s_empty;
return s_empty;
}
}
ColdProxy::ColdProxy (db::cell_index_type ci, db::Layout &layout, const ProxyContextInfo &info)
: Cell (ci, layout), mp_context_info (new ProxyContextInfo (info))
{
if (! info.lib_name.empty ()) {
tl::MutexLocker locker (&s_map_mutex);
s_proxies_per_library_name [info.lib_name].push_back (this);
}
}
ColdProxy::~ColdProxy ()
{
delete mp_context_info;
mp_context_info = 0;
}
Cell *
ColdProxy::clone (Layout &layout) const
{
Cell *cell = new ColdProxy (db::Cell::cell_index (), layout, *mp_context_info);
// copy the cell content
*cell = *this;
return cell;
}
std::string
ColdProxy::get_basic_name () const
{
if (! mp_context_info->pcell_name.empty ()) {
return "<defunc>" + mp_context_info->pcell_name;
} else if (! mp_context_info->cell_name.empty ()) {
return "<defunc>" + mp_context_info->cell_name;
} else {
return Cell::get_basic_name ();
}
}
std::string
ColdProxy::get_display_name () const
{
if (! mp_context_info->lib_name.empty ()) {
std::string stem = "<defunct>" + mp_context_info->lib_name + ".";
if (! mp_context_info->pcell_name.empty ()) {
return stem + mp_context_info->pcell_name;
} else if (! mp_context_info->cell_name.empty ()) {
return stem + mp_context_info->cell_name;
} else {
return stem + "<unknown>";
}
} else {
return Cell::get_display_name ();
}
}
std::string
ColdProxy::get_qualified_name () const
{
if (! mp_context_info->lib_name.empty ()) {
std::string stem = "<defunct>" + mp_context_info->lib_name + ".";
if (! mp_context_info->pcell_name.empty ()) {
if (mp_context_info->pcell_parameters.empty ()) {
return stem + mp_context_info->pcell_name;
} else {
// TODO: list parameters? Might be long.
return stem + mp_context_info->pcell_name + "(...)";
}
} else if (! mp_context_info->cell_name.empty ()) {
return stem + mp_context_info->cell_name;
} else {
return stem + "<unknown>";
}
} else {
return Cell::get_qualified_name ();
}
}
}

111
src/db/db/dbColdProxy.h Normal file
View File

@ -0,0 +1,111 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_dbColdProxy
#define HDR_dbColdProxy
#include "dbCommon.h"
#include "dbTypes.h"
#include "dbCell.h"
#include "tlObject.h"
namespace db
{
struct ProxyContextInfo;
/**
* @brief A cell specialization: a cold proxy representing a library or PCell which has gone out of scope
*
* If a PCell or library cell gets disconnected - for example, because the technology has changed or during
* development of PCell code - this proxy replaces the original one. It stores the connection information, so
* it can be regenerated when it becomes valid again.
*/
class DB_PUBLIC ColdProxy
: public Cell, public tl::Object
{
public:
/**
* @brief The constructor
*
* Creates a cold proxy represented by the ProxyContextInfo data.
*/
ColdProxy (db::cell_index_type ci, db::Layout &layout, const ProxyContextInfo &info);
/**
* @brief The destructor
*/
~ColdProxy ();
/**
* @brief Cloning
*/
virtual Cell *clone (Layout &layout) const;
/**
* @brief Get the library id
*/
const ProxyContextInfo &context_info () const
{
return *mp_context_info;
}
/**
* @brief Indicates that this cell is a proxy cell
*/
virtual bool is_proxy () const
{
return true;
}
/**
* @brief Gets a list of cold proxies for a given library name
*/
static const tl::weak_collection<ColdProxy> &cold_proxies_per_lib_name (const std::string &libname);
/**
* @brief Gets the basic name
*/
virtual std::string get_basic_name () const;
/**
* @brief Gets the display name
*/
virtual std::string get_display_name () const;
/**
* @brief Gets the qualified name
*/
virtual std::string get_qualified_name () const;
private:
ProxyContextInfo *mp_context_info;
};
}
#endif

View File

@ -30,6 +30,7 @@
#include "dbPCellVariant.h"
#include "dbPCellDeclaration.h"
#include "dbLibraryProxy.h"
#include "dbColdProxy.h"
#include "dbLibraryManager.h"
#include "dbLibrary.h"
#include "dbRegion.h"
@ -260,6 +261,65 @@ LayerIterator::operator*() const
return std::pair<unsigned int, const db::LayerProperties *> (m_layer_index, &m_layout.get_properties (m_layer_index));
}
// -----------------------------------------------------------------
// Implementation of the ProxyContextInfo class
ProxyContextInfo
ProxyContextInfo::deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to)
{
ProxyContextInfo info;
for (std::vector<std::string>::const_iterator i = from; i != to; ++i) {
tl::Extractor ex (i->c_str ());
if (ex.test ("LIB=")) {
info.lib_name = ex.skip ();
} else if (ex.test ("P(")) {
std::pair<std::string, tl::Variant> vv;
ex.read_word_or_quoted (vv.first);
ex.test (")");
ex.test ("=");
ex.read (vv.second);
info.pcell_parameters.insert (vv);
} else if (ex.test ("PCELL=")) {
info.pcell_name = ex.skip ();
} else if (ex.test ("CELL=")) {
info.cell_name = ex.skip ();
}
}
return info;
}
void
ProxyContextInfo::serialize (std::vector<std::string> &strings)
{
if (! lib_name.empty ()) {
strings.push_back ("LIB=" + lib_name);
}
for (std::map<std::string, tl::Variant> ::const_iterator p = pcell_parameters.begin (); p != pcell_parameters.end (); ++p) {
strings.push_back ("P(" + tl::to_word_or_quoted_string (p->first) + ")=" + p->second.to_parsable_string ());
}
if (! pcell_name.empty ()) {
strings.push_back ("PCELL=" + pcell_name);
}
if (! cell_name.empty ()) {
strings.push_back ("CELL=" + cell_name);
}
}
// -----------------------------------------------------------------
// Implementation of the Layout class
@ -522,12 +582,10 @@ Layout::set_technology_name (const std::string &tech)
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;
// substitute by a cold proxy
db::ProxyContextInfo info;
get_context_info (ci, info);
create_cold_proxy_as (info, ci);
} else {
@ -537,12 +595,10 @@ Layout::set_technology_name (const std::string &tech)
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;
// substitute by a cold proxy
db::ProxyContextInfo info;
get_context_info (ci, info);
create_cold_proxy_as (info, ci);
} else {
@ -566,12 +622,10 @@ Layout::set_technology_name (const std::string &tech)
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;
// unlink this proxy: substitute by a cold proxy
db::ProxyContextInfo info;
get_context_info (ci, info);
create_cold_proxy_as (info, ci);
} else {
@ -588,6 +642,9 @@ Layout::set_technology_name (const std::string &tech)
}
m_tech_name = tech;
// we may have re-established a connection for pending ("cold") proxies so we can try to restore them
restore_proxies ();
}
void
@ -1948,8 +2005,26 @@ static const std::vector<tl::Variant> &gauge_parameters (const std::vector<tl::V
}
}
void
Layout::replace_cell (cell_index_type target_cell_index, db::Cell *new_cell, bool retain_layout)
{
invalidate_hier ();
db::Cell *old_cell = m_cell_ptrs [target_cell_index];
if (old_cell) {
old_cell->unregister ();
if (retain_layout) {
new_cell->Cell::operator= (*old_cell);
}
}
m_cells.erase (iterator (old_cell));
m_cells.push_back_ptr (new_cell);
m_cell_ptrs [target_cell_index] = new_cell;
}
void
Layout::get_pcell_variant_as (pcell_id_type pcell_id, const std::vector<tl::Variant> &p, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping)
Layout::get_pcell_variant_as (pcell_id_type pcell_id, const std::vector<tl::Variant> &p, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping, bool retain_layout)
{
pcell_header_type *header = pcell_header (pcell_id);
tl_assert (header != 0);
@ -1963,16 +2038,13 @@ Layout::get_pcell_variant_as (pcell_id_type pcell_id, const std::vector<tl::Vari
tl_assert (! (manager () && manager ()->transacting ()));
tl_assert (m_cell_ptrs [target_cell_index] != 0);
invalidate_hier ();
m_cells.erase (iterator (m_cell_ptrs [target_cell_index]));
pcell_variant_type *variant = new pcell_variant_type (target_cell_index, *this, pcell_id, parameters);
m_cells.push_back_ptr (variant);
m_cell_ptrs [target_cell_index] = variant;
replace_cell (target_cell_index, variant, retain_layout);
// produce the layout
variant->update (layer_mapping);
if (! retain_layout) {
// produce the layout unless we retained it
variant->update (layer_mapping);
}
}
cell_index_type
@ -2316,8 +2388,20 @@ Layout::get_pcell_variant_cell (cell_index_type cell_index, const std::vector<tl
}
bool
Layout::get_context_info (cell_index_type cell_index, std::vector <std::string> &context_info) const
bool
Layout::get_context_info (cell_index_type cell_index, std::vector <std::string> &strings) const
{
ProxyContextInfo info;
if (! get_context_info (cell_index, info)) {
return false;
} else {
info.serialize (strings);
return true;
}
}
bool
Layout::get_context_info (cell_index_type cell_index, ProxyContextInfo &info) const
{
const db::Cell *cptr = &cell (cell_index);
const db::Layout *ly = this;
@ -2333,7 +2417,7 @@ Layout::get_context_info (cell_index_type cell_index, std::vector <std::string>
// one level of library indirection
ly = &lib->layout ();
cptr = &ly->cell (lib_proxy->library_cell_index ());
context_info.push_back ("LIB=" + lib->get_name ());
info.lib_name = lib->get_name ();
}
@ -2347,19 +2431,36 @@ Layout::get_context_info (cell_index_type cell_index, std::vector <std::string>
const std::vector<db::PCellParameterDeclaration> &pcp = pcell_decl->parameter_declarations ();
std::vector<db::PCellParameterDeclaration>::const_iterator pd = pcp.begin ();
for (std::vector<tl::Variant>::const_iterator p = pcell_variant->parameters ().begin (); p != pcell_variant->parameters ().end () && pd != pcp.end (); ++p, ++pd) {
context_info.push_back ("P(" + tl::to_word_or_quoted_string (pd->get_name ()) + ")=" + p->to_parsable_string ());
info.pcell_parameters.insert (std::make_pair (pd->get_name (), *p));
}
const db::PCellHeader *header = ly->pcell_header (pcell_variant->pcell_id ());
context_info.push_back ("PCELL=" + header->get_name ());
info.pcell_name = header->get_name ();
} else {
context_info.push_back ("CELL=" + std::string (ly->cell_name (cptr->cell_index ())));
info.cell_name = ly->cell_name (cptr->cell_index ());
}
return true;
}
void
Layout::restore_proxies (ImportLayerMapping *layer_mapping)
{
std::vector<db::ColdProxy *> cold_proxies;
for (iterator c = begin (); c != end (); ++c) {
db::ColdProxy *proxy = dynamic_cast<db::ColdProxy *> (c.operator-> ());
if (proxy) {
cold_proxies.push_back (proxy);
}
}
for (std::vector<db::ColdProxy *>::const_iterator p = cold_proxies.begin (); p != cold_proxies.end (); ++p) {
recover_proxy_as ((*p)->cell_index (), (*p)->context_info (), layer_mapping);
}
}
bool
Layout::recover_proxy_as (cell_index_type cell_index, std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to, ImportLayerMapping *layer_mapping)
{
@ -2367,17 +2468,21 @@ Layout::recover_proxy_as (cell_index_type cell_index, std::vector <std::string>:
return false;
}
tl::Extractor ex (from->c_str ());
return recover_proxy_as (cell_index, ProxyContextInfo::deserialize (from, to), layer_mapping);
}
if (ex.test ("LIB=")) {
bool
Layout::recover_proxy_as (cell_index_type cell_index, const ProxyContextInfo &info, ImportLayerMapping *layer_mapping)
{
if (! info.lib_name.empty ()) {
std::string lib_name = ex.skip ();
Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (lib_name, m_tech_name);
if (! lib) {
return false;
db::Cell *lib_cell = 0;
Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (info.lib_name, m_tech_name);
if (lib) {
lib_cell = lib->layout ().recover_proxy_no_lib (info);
}
db::Cell *lib_cell = lib->layout ().recover_proxy (from + 1, to);
if (lib_cell) {
get_lib_proxy_as (lib, lib_cell->cell_index (), cell_index, layer_mapping);
return true;
@ -2385,38 +2490,28 @@ Layout::recover_proxy_as (cell_index_type cell_index, std::vector <std::string>:
} else {
std::map<std::string, tl::Variant> parameters;
if (! info.pcell_name.empty ()) {
while (from != to && (ex = tl::Extractor (from->c_str ())).test ("P(")) {
std::string name;
ex.read_word_or_quoted (name);
ex.test (")");
ex.test ("=");
ex.read (parameters.insert (std::make_pair (name, tl::Variant ())).first->second);
++from;
}
if (ex.test ("PCELL=")) {
std::pair<bool, pcell_id_type> pc = pcell_by_name (ex.skip ());
std::pair<bool, pcell_id_type> pc = pcell_by_name (info.pcell_name.c_str ());
if (pc.first) {
get_pcell_variant_as (pc.second, pcell_declaration (pc.second)->map_parameters (parameters), cell_index, layer_mapping);
get_pcell_variant_as (pc.second, pcell_declaration (pc.second)->map_parameters (info.pcell_parameters), cell_index, layer_mapping);
return true;
}
} else if (ex.test ("CELL=")) {
} else if (! info.cell_name.empty ()) {
// This should not happen. A cell (given by the cell index) cannot be proxy to another cell in the same layout.
// This should not happen. A cell (given by the cell name) cannot be proxy to another cell in the same layout.
tl_assert (false);
}
}
if (! dynamic_cast<db::ColdProxy *> (m_cell_ptrs [cell_index])) {
// create a cold proxy representing the context information so we can restore it
create_cold_proxy_as (info, cell_index);
}
return false;
}
@ -2427,55 +2522,54 @@ Layout::recover_proxy (std::vector <std::string>::const_iterator from, std::vect
return 0;
}
tl::Extractor ex (from->c_str ());
return recover_proxy (ProxyContextInfo::deserialize (from, to));
}
if (ex.test ("LIB=")) {
db::Cell *
Layout::recover_proxy (const ProxyContextInfo &info)
{
if (! info.lib_name.empty ()) {
std::string lib_name = ex.skip ();
Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (lib_name, m_tech_name);
if (! lib) {
return 0;
Library *lib = db::LibraryManager::instance ().lib_ptr_by_name (info.lib_name, m_tech_name);
db::Cell *lib_cell = 0;
if (lib) {
lib_cell = lib->layout ().recover_proxy_no_lib (info);
}
db::Cell *lib_cell = lib->layout ().recover_proxy (from + 1, to);
if (lib_cell) {
cell_index_type cell_index = get_lib_proxy (lib, lib_cell->cell_index ());
return &cell (cell_index);
return m_cell_ptrs [get_lib_proxy (lib, lib_cell->cell_index ())];
}
} else {
std::map<std::string, tl::Variant> parameters;
while (from != to && (ex = tl::Extractor (from->c_str ())).test ("P(")) {
std::string name;
ex.read_word_or_quoted (name);
ex.test (")");
ex.test ("=");
ex.read (parameters.insert (std::make_pair (name, tl::Variant ())).first->second);
++from;
db::Cell *proxy = recover_proxy_no_lib (info);
if (proxy) {
return proxy;
}
if (ex.test ("PCELL=")) {
}
std::pair<bool, pcell_id_type> pc = pcell_by_name (ex.skip ());
if (pc.first) {
cell_index_type cell_index = get_pcell_variant (pc.second, pcell_declaration (pc.second)->map_parameters (parameters));
return &cell (cell_index);
}
return m_cell_ptrs [create_cold_proxy (info)];
}
} else if (ex.test ("CELL=")) {
db::Cell *
Layout::recover_proxy_no_lib (const ProxyContextInfo &info)
{
if (! info.pcell_name.empty ()) {
std::pair<bool, cell_index_type> cc = cell_by_name (ex.skip ());
if (cc.first) {
return &cell (cc.second);
}
std::pair<bool, pcell_id_type> pc = pcell_by_name (info.pcell_name.c_str ());
if (pc.first) {
cell_index_type cell_index = get_pcell_variant (pc.second, pcell_declaration (pc.second)->map_parameters (info.pcell_parameters));
return m_cell_ptrs [cell_index];
}
}
} else if (! info.cell_name.empty ()) {
std::pair<bool, cell_index_type> cc = cell_by_name (info.cell_name.c_str ());
if (cc.first) {
return m_cell_ptrs [cc.second];
}
}
@ -2507,21 +2601,18 @@ Layout::unregister_lib_proxy (db::LibraryProxy *lib_proxy)
}
void
Layout::get_lib_proxy_as (Library *lib, cell_index_type cell_index, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping)
Layout::get_lib_proxy_as (Library *lib, cell_index_type cell_index, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping, bool retain_layout)
{
tl_assert (! (manager () && manager ()->transacting ()));
tl_assert (m_cell_ptrs [target_cell_index] != 0);
invalidate_hier ();
m_cells.erase (iterator (m_cell_ptrs [target_cell_index]));
LibraryProxy *proxy = new LibraryProxy (target_cell_index, *this, lib->get_id (), cell_index);
m_cells.push_back_ptr (proxy);
m_cell_ptrs [target_cell_index] = proxy;
replace_cell (target_cell_index, proxy, retain_layout);
// produce the layout
proxy->update (layer_mapping);
if (! retain_layout) {
// produce the layout unless we retained it
proxy->update (layer_mapping);
}
}
cell_index_type
@ -2552,7 +2643,7 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
manager ()->queue (this, new NewRemoveCellOp (new_index, m_cell_names [new_index], false /*new*/, 0));
}
// produce the layout
// produce the layout
proxy->update ();
return new_index;
@ -2560,6 +2651,47 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
}
}
cell_index_type
Layout::create_cold_proxy (const db::ProxyContextInfo &info)
{
// create a new unique name
std::string b;
if (! info.cell_name.empty ()) {
b = info.cell_name;
} else if (! info.pcell_name.empty ()) {
b = info.pcell_name;
}
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
b = uniquify_cell_name (b.c_str ());
}
// create a new cell (a LibraryProxy)
cell_index_type new_index = allocate_new_cell ();
ColdProxy *proxy = new ColdProxy (new_index, *this, info);
m_cells.push_back_ptr (proxy);
m_cell_ptrs [new_index] = proxy;
// enter it's index and cell_name
register_cell_name (b.c_str (), new_index);
if (manager () && manager ()->transacting ()) {
manager ()->queue (this, new NewRemoveCellOp (new_index, m_cell_names [new_index], false /*new*/, 0));
}
return new_index;
}
void
Layout::create_cold_proxy_as (const db::ProxyContextInfo &info, cell_index_type target_cell_index)
{
tl_assert (! (manager () && manager ()->transacting ()));
tl_assert (m_cell_ptrs [target_cell_index] != 0);
ColdProxy *proxy = new ColdProxy (target_cell_index, *this, info);
replace_cell (target_cell_index, proxy, true);
}
void
Layout::redo (db::Op *op)
{

View File

@ -457,6 +457,20 @@ public:
virtual std::pair <bool, unsigned int> map_layer (const LayerProperties &lprops) = 0;
};
/**
* @brief A binary object representing context information for regenerating library proxies and PCells
*/
struct DB_PUBLIC ProxyContextInfo
{
std::string lib_name;
std::string cell_name;
std::string pcell_name;
std::map<std::string, tl::Variant> pcell_parameters;
static ProxyContextInfo deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to);
void serialize (std::vector<std::string> &strings);
};
/**
* @brief The layout object
*
@ -863,8 +877,9 @@ public:
* @param parameters The PCell parameters
* @param cell_index The cell index which is to be replaced by the PCell variant proxy
* @param layer_mapping The optional layer mapping object that maps the PCell layers to the layout's layers
* @param retain_layout Set to true for not using update() on the PCell but to retain existing layout (conservative approach)
*/
void get_pcell_variant_as (pcell_id_type pcell_id, const std::vector<tl::Variant> &parameters, cell_index_type cell_index, ImportLayerMapping *layer_mapping = 0);
void get_pcell_variant_as (pcell_id_type pcell_id, const std::vector<tl::Variant> &parameters, cell_index_type cell_index, ImportLayerMapping *layer_mapping = 0, bool retain_layout = false);
/**
* @brief Get the PCell variant cell of a existing cell with new parameters
@ -1010,9 +1025,21 @@ public:
/**
* @brief Get the proxy cell (index) for a given library an cell index (inside that library)
*
* This method replaces the cell with the given target cell index by a library.
* @param retain_layout Set to true for not using update() on the PCell but to retain existing layout (conservative approach)
*
* This method replaces the cell with the given target cell index by a library.
*/
void get_lib_proxy_as (Library *lib, cell_index_type cell_index, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping = 0);
void get_lib_proxy_as (Library *lib, cell_index_type cell_index, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping = 0, bool retain_layout = false);
/**
* @brief Creates a cold proxy representing the given context information
*/
cell_index_type create_cold_proxy (const db::ProxyContextInfo &info);
/**
* @brief Subsitutes the given cell by a cold proxy representing the given context information
*/
void create_cold_proxy_as (const db::ProxyContextInfo &info, cell_index_type cell_index);
/**
* @brief Get the context information for a given cell (for writing into a file)
@ -1024,6 +1051,11 @@ public:
*/
bool get_context_info (cell_index_type cell_index, std::vector <std::string> &context_info) const;
/**
* @brief Gets the context information as a binary object
*/
bool get_context_info (cell_index_type cell_index, ProxyContextInfo &context_info) const;
/**
* @brief Recover a proxy cell from the given context info.
*
@ -1035,6 +1067,11 @@ public:
*/
db::Cell *recover_proxy (std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to);
/**
* @brief Recover a proxy cell from the given binary context info object.
*/
db::Cell *recover_proxy (const ProxyContextInfo &context_info);
/**
* @brief Recover a proxy cell from the given context info.
*
@ -1050,6 +1087,27 @@ public:
*/
bool recover_proxy_as (cell_index_type cell_index, std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to, ImportLayerMapping *layer_mapping = 0);
/**
* @brief Recover a proxy cell from the given binary context info object
*
* See the string-based version of "recover_proxy_as" for details.
*/
bool recover_proxy_as (cell_index_type cell_index, const ProxyContextInfo &context_info, ImportLayerMapping *layer_mapping = 0);
/**
* @brief Restores proxies as far as possible
*
* This feature can be used after a library update to make sure that proxies are updated.
* Library updates may enabled lost connections which are help in cold proxies. This method will recover
* these connections.
*/
void restore_proxies(ImportLayerMapping *layer_mapping = 0);
/**
* @brief Replaces the given cell index with the new cell
*/
void replace_cell (cell_index_type target_cell_index, db::Cell *new_cell, bool retain_layout);
/**
* @brief Delete a cell plus the subcells not used otherwise
*
@ -1853,6 +1911,11 @@ private:
* @brief Implementation of prune_cells and some prune_subcells variants
*/
void do_prune_cells_or_subcells (const std::set<cell_index_type> &ids, int levels, bool subcells);
/**
* @brief Recovers a proxy without considering the library from context_info
*/
db::Cell *recover_proxy_no_lib (const ProxyContextInfo &context_info);
};
/**

View File

@ -191,12 +191,10 @@ 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));
delete old_cell;
// substitute by a cold proxy
db::ProxyContextInfo info;
r->first->get_context_info (ci, info);
r->first->create_cold_proxy_as (info, ci);
} else {
@ -204,12 +202,10 @@ Library::remap_to (db::Library *other)
const db::PCellDeclaration *new_pcell_decl = other->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 = 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));
delete old_cell;
// substitute by a cold proxy
db::ProxyContextInfo info;
r->first->get_context_info (ci, info);
r->first->create_cold_proxy_as (info, ci);
} else {
@ -234,12 +230,10 @@ 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));
delete old_cell;
// substitute by a cold proxy
db::ProxyContextInfo info;
r->first->get_context_info (ci, info);
r->first->create_cold_proxy_as (info, ci);
} else {

View File

@ -24,6 +24,7 @@
#include "dbLibraryManager.h"
#include "dbLibrary.h"
#include "dbCommon.h"
#include "dbColdProxy.h"
#include "tlAssert.h"
#include "tlStaticObjects.h"
@ -158,6 +159,21 @@ LibraryManager::register_lib (Library *library)
l = m_lib_by_name.find (library->get_name ());
m_lib_by_name.insert (l, std::make_pair (library->get_name (), id));
// take care of cold referrers - these may not get valid
// NOTE: this will try to substitute the cold proxies we may have generated during "remap_to" above, but
// "restore_proxies" takes care not to re-substitute cold proxies.
const tl::weak_collection<db::ColdProxy> &cold_proxies = db::ColdProxy::cold_proxies_per_lib_name (library->get_name ());
std::set<db::Layout *> to_refresh;
for (tl::weak_collection<db::ColdProxy>::const_iterator p = cold_proxies.begin (); p != cold_proxies.end (); ++p) {
to_refresh.insert (const_cast<db::Layout *> (p->layout ()));
}
for (std::set<db::Layout *>::const_iterator l = to_refresh.begin (); l != to_refresh.end (); ++l) {
(*l)->restore_proxies (0);
}
// issue the change notification
changed_event ();
return id;

View File

@ -99,8 +99,6 @@ LibraryProxy::remap (lib_id_type lib_id, cell_index_type lib_cell_index)
m_lib_id = lib_id;
m_library_cell_index = lib_cell_index;
// It's important to register at the new library, but the old library is about to the deleted, so we don't unregister.
// That does not disturb the old library iterating over the layouts.
db::Library *lib = db::LibraryManager::instance ().lib (m_lib_id);
if (lib) {
lib->register_proxy (this, layout ());

View File

@ -358,17 +358,21 @@ GDS2ReaderBase::do_read (db::Layout &layout)
db::cell_index_type cell_index = make_cell (layout, m_cellname);
db::Cell *cell = &layout.cell (cell_index);
bool ignore_cell = false;
std::map <tl::string, std::vector <std::string> >::const_iterator ctx = m_context_info.find (m_cellname);
if (ctx != m_context_info.end ()) {
GDS2ReaderLayerMapping layer_mapping (this, &layout, m_create_layers);
if (layout.recover_proxy_as (cell_index, ctx->second.begin (), ctx->second.end (), &layer_mapping)) {
// ignore everything in that cell since it is created by the import:
cell = 0;
ignore_cell = true;
}
}
db::Cell *cell = 0;
if (! ignore_cell) {
cell = &layout.cell (cell_index);
}
long attr = 0;
db::PropertiesRepository::properties_set cell_properties;