mirror of https://github.com/KLayout/klayout.git
Improving Layout::cleanup to consolidate library and cold proxies and to establish proper cell names if possible
This commit is contained in:
parent
dcc7f28c77
commit
a6dce8c2ad
|
|
@ -60,14 +60,36 @@ ColdProxy::ColdProxy (db::cell_index_type ci, db::Layout &layout, const LayoutOr
|
||||||
}
|
}
|
||||||
i->second->push_back (this);
|
i->second->push_back (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layout.register_cold_proxy (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ColdProxy::~ColdProxy ()
|
ColdProxy::~ColdProxy ()
|
||||||
{
|
{
|
||||||
|
if (layout ()) {
|
||||||
|
layout ()->unregister_cold_proxy (this);
|
||||||
|
}
|
||||||
|
|
||||||
delete mp_context_info;
|
delete mp_context_info;
|
||||||
mp_context_info = 0;
|
mp_context_info = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ColdProxy::unregister ()
|
||||||
|
{
|
||||||
|
if (layout ()) {
|
||||||
|
layout ()->unregister_cold_proxy (this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ColdProxy::reregister ()
|
||||||
|
{
|
||||||
|
if (layout ()) {
|
||||||
|
layout ()->register_cold_proxy (this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Cell *
|
Cell *
|
||||||
ColdProxy::clone (Layout &layout) const
|
ColdProxy::clone (Layout &layout) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,16 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplemented from Cell: unregisters the proxy at the layout
|
||||||
|
*/
|
||||||
|
virtual void unregister ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplemented from Cell: reregisters the proxy at the layout
|
||||||
|
*/
|
||||||
|
virtual void reregister ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a list of cold proxies for a given library name
|
* @brief Gets a list of cold proxies for a given library name
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,37 @@ private:
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// Implementation of the ProxyContextInfo class
|
// Implementation of the ProxyContextInfo class
|
||||||
|
|
||||||
|
bool
|
||||||
|
LayoutOrCellContextInfo::operator== (const LayoutOrCellContextInfo &other) const
|
||||||
|
{
|
||||||
|
return lib_name == other.lib_name &&
|
||||||
|
cell_name == other.cell_name &&
|
||||||
|
pcell_name == other.pcell_name &&
|
||||||
|
pcell_parameters == other.pcell_parameters &&
|
||||||
|
meta_info == other.meta_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LayoutOrCellContextInfo::operator< (const LayoutOrCellContextInfo &other) const
|
||||||
|
{
|
||||||
|
if (lib_name != other.lib_name) {
|
||||||
|
return lib_name < other.lib_name;
|
||||||
|
}
|
||||||
|
if (cell_name != other.cell_name) {
|
||||||
|
return cell_name < other.cell_name;
|
||||||
|
}
|
||||||
|
if (pcell_name != other.pcell_name) {
|
||||||
|
return pcell_name < other.pcell_name;
|
||||||
|
}
|
||||||
|
if (pcell_parameters != other.pcell_parameters) {
|
||||||
|
return pcell_parameters < other.pcell_parameters;
|
||||||
|
}
|
||||||
|
if (meta_info != other.meta_info) {
|
||||||
|
return meta_info < other.meta_info;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LayoutOrCellContextInfo
|
LayoutOrCellContextInfo
|
||||||
LayoutOrCellContextInfo::deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to)
|
LayoutOrCellContextInfo::deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to)
|
||||||
{
|
{
|
||||||
|
|
@ -540,6 +571,7 @@ Layout::clear ()
|
||||||
m_pcell_ids.clear ();
|
m_pcell_ids.clear ();
|
||||||
|
|
||||||
m_lib_proxy_map.clear ();
|
m_lib_proxy_map.clear ();
|
||||||
|
m_cold_proxy_map.clear ();
|
||||||
m_meta_info.clear ();
|
m_meta_info.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -568,6 +600,7 @@ Layout::operator= (const Layout &d)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lib_proxy_map = d.m_lib_proxy_map;
|
m_lib_proxy_map = d.m_lib_proxy_map;
|
||||||
|
m_cold_proxy_map = d.m_cold_proxy_map;
|
||||||
|
|
||||||
m_cell_ptrs.resize (d.m_cell_ptrs.size (), 0);
|
m_cell_ptrs.resize (d.m_cell_ptrs.size (), 0);
|
||||||
|
|
||||||
|
|
@ -809,6 +842,7 @@ Layout::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat
|
||||||
db::mem_stat (stat, purpose, cat, m_pcells, true, (void *) this);
|
db::mem_stat (stat, purpose, cat, m_pcells, true, (void *) this);
|
||||||
db::mem_stat (stat, purpose, cat, m_pcell_ids, true, (void *) this);
|
db::mem_stat (stat, purpose, cat, m_pcell_ids, true, (void *) this);
|
||||||
db::mem_stat (stat, purpose, cat, m_lib_proxy_map, true, (void *) this);
|
db::mem_stat (stat, purpose, cat, m_lib_proxy_map, true, (void *) this);
|
||||||
|
db::mem_stat (stat, purpose, cat, m_cold_proxy_map, true, (void *) this);
|
||||||
db::mem_stat (stat, purpose, cat, m_meta_info, true, (void *) this);
|
db::mem_stat (stat, purpose, cat, m_meta_info, true, (void *) this);
|
||||||
db::mem_stat (stat, purpose, cat, m_shape_repository, true, (void *) this);
|
db::mem_stat (stat, purpose, cat, m_shape_repository, true, (void *) this);
|
||||||
db::mem_stat (stat, purpose, cat, m_array_repository, true, (void *) this);
|
db::mem_stat (stat, purpose, cat, m_array_repository, true, (void *) this);
|
||||||
|
|
@ -1505,6 +1539,11 @@ Layout::register_cell_name (const char *name, cell_index_type ci)
|
||||||
void
|
void
|
||||||
Layout::rename_cell (cell_index_type id, const char *name)
|
Layout::rename_cell (cell_index_type id, const char *name)
|
||||||
{
|
{
|
||||||
|
static const char *anonymous_name = "";
|
||||||
|
if (! name) {
|
||||||
|
name = anonymous_name;
|
||||||
|
}
|
||||||
|
|
||||||
tl_assert (id < m_cell_names.size ());
|
tl_assert (id < m_cell_names.size ());
|
||||||
|
|
||||||
if (strcmp (m_cell_names [id], name) != 0) {
|
if (strcmp (m_cell_names [id], name) != 0) {
|
||||||
|
|
@ -1521,7 +1560,10 @@ Layout::rename_cell (cell_index_type id, const char *name)
|
||||||
delete [] m_cell_names [id];
|
delete [] m_cell_names [id];
|
||||||
m_cell_names [id] = cp;
|
m_cell_names [id] = cp;
|
||||||
|
|
||||||
m_cell_map.insert (std::make_pair (cp, id));
|
// NOTE: anonymous cells (empty name string) are not registered in the cell name map
|
||||||
|
if (*cp != 0) {
|
||||||
|
m_cell_map.insert (std::make_pair (cp, id));
|
||||||
|
}
|
||||||
|
|
||||||
// to enforce a redraw and a rebuild
|
// to enforce a redraw and a rebuild
|
||||||
cell_name_changed ();
|
cell_name_changed ();
|
||||||
|
|
@ -1690,27 +1732,119 @@ Layout::cleanup (const std::set<db::cell_index_type> &keep)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tl::verbosity () >= 30) {
|
||||||
|
tl::info << "Cleaning up layout ..";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do some polishing of the proxies - sometimes, specifically when resolving indirect library references,
|
||||||
|
// different proxies to the same library object exist. We can identify them and clean them up, so there
|
||||||
|
// is a single reference. We can also try to ensure that cell names reflect the library cell names.
|
||||||
|
// The latter is good for LVS for example.
|
||||||
|
|
||||||
|
{
|
||||||
|
db::LayoutLocker locker (this);
|
||||||
|
|
||||||
|
// join library proxies pointing to the same object
|
||||||
|
|
||||||
|
for (auto c = m_lib_proxy_map.begin (); c != m_lib_proxy_map.end (); ) {
|
||||||
|
|
||||||
|
auto c0 = c++;
|
||||||
|
size_t n = 1;
|
||||||
|
while (c != m_lib_proxy_map.end () && c->first == c0->first) {
|
||||||
|
++n;
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > 1) {
|
||||||
|
auto cc = c0;
|
||||||
|
++cc;
|
||||||
|
while (cc != c) {
|
||||||
|
if (keep.find (cc->second) == keep.end ()) {
|
||||||
|
if (tl::verbosity () >= 30) {
|
||||||
|
tl::info << "Joining lib proxy " << cell_name (cc->second) << " into " << cell_name (c0->second);
|
||||||
|
}
|
||||||
|
replace_instances_of (cc->second, c0->second);
|
||||||
|
}
|
||||||
|
++cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// join cold proxies pointing to the same object
|
||||||
|
|
||||||
|
for (auto c = m_cold_proxy_map.begin (); c != m_cold_proxy_map.end (); ) {
|
||||||
|
|
||||||
|
auto c0 = c++;
|
||||||
|
size_t n = 1;
|
||||||
|
while (c != m_cold_proxy_map.end () && c->first == c0->first) {
|
||||||
|
++n;
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > 1) {
|
||||||
|
auto cc = c0;
|
||||||
|
++cc;
|
||||||
|
while (cc != c) {
|
||||||
|
if (keep.find (cc->second) == keep.end ()) {
|
||||||
|
if (tl::verbosity () >= 30) {
|
||||||
|
tl::info << "Joining cold proxy " << cell_name (cc->second) << " into " << cell_name (c0->second);
|
||||||
|
}
|
||||||
|
replace_instances_of (cc->second, c0->second);
|
||||||
|
}
|
||||||
|
++cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<cell_index_type> cells_to_delete;
|
||||||
|
|
||||||
// deleting cells may create new top cells which need to be deleted as well, hence we iterate
|
// deleting cells may create new top cells which need to be deleted as well, hence we iterate
|
||||||
// until there are no more cells to delete
|
// until there are no more cells to delete
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
// delete all cells that are top cells and are proxies. Those cells are proxies no longer required.
|
// delete all cells that are top cells and are proxies. Those cells are proxies no longer required.
|
||||||
std::set<cell_index_type> cells_to_delete;
|
|
||||||
for (top_down_iterator c = begin_top_down (); c != end_top_cells (); ++c) {
|
for (top_down_iterator c = begin_top_down (); c != end_top_cells (); ++c) {
|
||||||
if (cell (*c).is_proxy ()) {
|
if (cell (*c).is_proxy () && keep.find (*c) == keep.end ()) {
|
||||||
cells_to_delete.insert (*c);
|
cells_to_delete.insert (*c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::set<db::cell_index_type>::const_iterator k = keep.begin (); k != keep.end (); ++k) {
|
|
||||||
cells_to_delete.erase (*k);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cells_to_delete.empty ()) {
|
if (cells_to_delete.empty ()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_cells (cells_to_delete);
|
delete_cells (cells_to_delete);
|
||||||
|
cells_to_delete.clear ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to ensure that cell names reflect the library cell names. The latter is good for LVS for example.
|
||||||
|
|
||||||
|
for (auto c = m_lib_proxy_map.begin (); c != m_lib_proxy_map.end (); ++c) {
|
||||||
|
|
||||||
|
std::string bn = cell (c->second).get_basic_name ();
|
||||||
|
if (bn != cell_name (c->second) && ! cell_by_name (bn.c_str ()).first) {
|
||||||
|
if (tl::verbosity () >= 30) {
|
||||||
|
tl::info << "Renaming lib proxy " << cell_name (c->second) << " to " << bn;
|
||||||
|
}
|
||||||
|
rename_cell (c->second, bn.c_str ());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto c = m_cold_proxy_map.begin (); c != m_cold_proxy_map.end (); ++c) {
|
||||||
|
|
||||||
|
std::string bn = cell (c->second).get_basic_name ();
|
||||||
|
if (bn != cell_name (c->second) && ! cell_by_name (bn.c_str ()).first) {
|
||||||
|
if (tl::verbosity () >= 30) {
|
||||||
|
tl::info << "Renaming cold proxy " << cell_name (c->second) << " to " << bn;
|
||||||
|
}
|
||||||
|
rename_cell (c->second, bn.c_str ());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3151,13 +3285,32 @@ Layout::variant_name (cell_index_type cell_index) const
|
||||||
void
|
void
|
||||||
Layout::register_lib_proxy (db::LibraryProxy *lib_proxy)
|
Layout::register_lib_proxy (db::LibraryProxy *lib_proxy)
|
||||||
{
|
{
|
||||||
m_lib_proxy_map.insert (std::make_pair (std::make_pair (lib_proxy->lib_id (), lib_proxy->library_cell_index ()), lib_proxy->Cell::cell_index ()));
|
auto key = std::make_pair (lib_proxy->lib_id (), lib_proxy->library_cell_index ());
|
||||||
|
|
||||||
|
auto l = m_lib_proxy_map.find (key);
|
||||||
|
while (l != m_lib_proxy_map.end () && l->first == key) {
|
||||||
|
if (l->second == lib_proxy->Cell::cell_index ()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lib_proxy_map.insert (std::make_pair (key, lib_proxy->Cell::cell_index ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Layout::unregister_lib_proxy (db::LibraryProxy *lib_proxy)
|
Layout::unregister_lib_proxy (db::LibraryProxy *lib_proxy)
|
||||||
{
|
{
|
||||||
m_lib_proxy_map.erase (std::make_pair (lib_proxy->lib_id (), lib_proxy->library_cell_index ()));
|
auto key = std::make_pair (lib_proxy->lib_id (), lib_proxy->library_cell_index ());
|
||||||
|
|
||||||
|
auto l = m_lib_proxy_map.find (key);
|
||||||
|
while (l != m_lib_proxy_map.end () && l->first == key) {
|
||||||
|
if (l->second == lib_proxy->Cell::cell_index ()) {
|
||||||
|
m_lib_proxy_map.erase (l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3177,9 +3330,13 @@ Layout::get_lib_proxy_as (Library *lib, cell_index_type cell_index, cell_index_t
|
||||||
cell_index_type
|
cell_index_type
|
||||||
Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
|
Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
|
||||||
{
|
{
|
||||||
lib_proxy_map::const_iterator lp = m_lib_proxy_map.find (std::make_pair (lib->get_id (), cell_index));
|
auto key = std::make_pair (lib->get_id (), cell_index);
|
||||||
if (lp != m_lib_proxy_map.end ()) {
|
|
||||||
|
lib_proxy_map::const_iterator lp = m_lib_proxy_map.find (key);
|
||||||
|
if (lp != m_lib_proxy_map.end () && lp->first == key) {
|
||||||
|
|
||||||
return lp->second;
|
return lp->second;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// create a new unique name
|
// create a new unique name
|
||||||
|
|
@ -3210,35 +3367,82 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Layout::register_cold_proxy (db::ColdProxy *cold_proxy)
|
||||||
|
{
|
||||||
|
auto l = m_cold_proxy_map.find (cold_proxy->context_info ());
|
||||||
|
while (l != m_cold_proxy_map.end () && l->first == cold_proxy->context_info ()) {
|
||||||
|
if (l->second == cold_proxy->Cell::cell_index ()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cold_proxy_map.insert (std::make_pair (cold_proxy->context_info (), cold_proxy->Cell::cell_index ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Layout::unregister_cold_proxy (db::ColdProxy *cold_proxy)
|
||||||
|
{
|
||||||
|
auto l = m_cold_proxy_map.find (cold_proxy->context_info ());
|
||||||
|
while (l != m_cold_proxy_map.end () && l->first == cold_proxy->context_info ()) {
|
||||||
|
if (l->second == cold_proxy->Cell::cell_index ()) {
|
||||||
|
m_cold_proxy_map.erase (l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, cell_index_type>
|
||||||
|
Layout::find_cold_proxy (const db::LayoutOrCellContextInfo &info)
|
||||||
|
{
|
||||||
|
cold_proxy_map::const_iterator lp = m_cold_proxy_map.find (info);
|
||||||
|
if (lp != m_cold_proxy_map.end () && lp->first == info) {
|
||||||
|
return std::make_pair (true, lp->second);
|
||||||
|
} else {
|
||||||
|
return std::make_pair (false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cell_index_type
|
cell_index_type
|
||||||
Layout::create_cold_proxy (const db::LayoutOrCellContextInfo &info)
|
Layout::create_cold_proxy (const db::LayoutOrCellContextInfo &info)
|
||||||
{
|
{
|
||||||
// create a new unique name
|
cold_proxy_map::const_iterator lp = m_cold_proxy_map.find (info);
|
||||||
std::string b;
|
if (lp != m_cold_proxy_map.end () && lp->first == info) {
|
||||||
if (! info.cell_name.empty ()) {
|
|
||||||
b = info.cell_name;
|
return lp->second;
|
||||||
} else if (! info.pcell_name.empty ()) {
|
|
||||||
b = info.pcell_name;
|
} else {
|
||||||
|
|
||||||
|
// 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 its 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;
|
||||||
|
|
||||||
}
|
}
|
||||||
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 its 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
|
void
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ class PCellDeclaration;
|
||||||
class PCellHeader;
|
class PCellHeader;
|
||||||
class Library;
|
class Library;
|
||||||
class LibraryProxy;
|
class LibraryProxy;
|
||||||
|
class ColdProxy;
|
||||||
class CellMapping;
|
class CellMapping;
|
||||||
class LayerMapping;
|
class LayerMapping;
|
||||||
class Region;
|
class Region;
|
||||||
|
|
@ -427,6 +428,9 @@ struct DB_PUBLIC LayoutOrCellContextInfo
|
||||||
std::map<std::string, tl::Variant> pcell_parameters;
|
std::map<std::string, tl::Variant> pcell_parameters;
|
||||||
std::map<std::string, std::pair<tl::Variant, std::string> > meta_info;
|
std::map<std::string, std::pair<tl::Variant, std::string> > meta_info;
|
||||||
|
|
||||||
|
bool operator== (const LayoutOrCellContextInfo &other) const;
|
||||||
|
bool operator< (const LayoutOrCellContextInfo &other) const;
|
||||||
|
|
||||||
static LayoutOrCellContextInfo deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to);
|
static LayoutOrCellContextInfo deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to);
|
||||||
void serialize (std::vector<std::string> &strings);
|
void serialize (std::vector<std::string> &strings);
|
||||||
|
|
||||||
|
|
@ -469,7 +473,8 @@ public:
|
||||||
typedef db::pcell_id_type pcell_id_type;
|
typedef db::pcell_id_type pcell_id_type;
|
||||||
typedef std::map<std::string, pcell_id_type> pcell_name_map;
|
typedef std::map<std::string, pcell_id_type> pcell_name_map;
|
||||||
typedef pcell_name_map::const_iterator pcell_iterator;
|
typedef pcell_name_map::const_iterator pcell_iterator;
|
||||||
typedef std::map<std::pair<lib_id_type, cell_index_type>, cell_index_type> lib_proxy_map;
|
typedef std::multimap<std::pair<lib_id_type, cell_index_type>, cell_index_type> lib_proxy_map;
|
||||||
|
typedef std::multimap<db::LayoutOrCellContextInfo, cell_index_type> cold_proxy_map;
|
||||||
typedef LayerIterator layer_iterator;
|
typedef LayerIterator layer_iterator;
|
||||||
typedef size_t meta_info_name_id_type;
|
typedef size_t meta_info_name_id_type;
|
||||||
typedef std::map<meta_info_name_id_type, MetaInfo> meta_info_map;
|
typedef std::map<meta_info_name_id_type, MetaInfo> meta_info_map;
|
||||||
|
|
@ -1003,6 +1008,12 @@ public:
|
||||||
*/
|
*/
|
||||||
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);
|
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 Find an existing cold proxy for a given context
|
||||||
|
* @return A pair of success flag and cell index of the proxy
|
||||||
|
*/
|
||||||
|
std::pair<bool, cell_index_type> find_cold_proxy (const db::LayoutOrCellContextInfo &info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a cold proxy representing the given context information
|
* @brief Creates a cold proxy representing the given context information
|
||||||
*/
|
*/
|
||||||
|
|
@ -1839,6 +1850,20 @@ public:
|
||||||
*/
|
*/
|
||||||
void unregister_lib_proxy (db::LibraryProxy *lib_proxy);
|
void unregister_lib_proxy (db::LibraryProxy *lib_proxy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a cold proxy
|
||||||
|
*
|
||||||
|
* This method is used by ColdProxy to register itself.
|
||||||
|
*/
|
||||||
|
void register_cold_proxy (db::ColdProxy *cold_proxy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregister a cold proxy
|
||||||
|
*
|
||||||
|
* This method is used by ColdProxy to unregister itself.
|
||||||
|
*/
|
||||||
|
void unregister_cold_proxy (db::ColdProxy *cold_proxy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the editable status of this layout
|
* @brief Gets the editable status of this layout
|
||||||
*
|
*
|
||||||
|
|
@ -2153,6 +2178,7 @@ private:
|
||||||
std::vector<pcell_header_type *> m_pcells;
|
std::vector<pcell_header_type *> m_pcells;
|
||||||
pcell_name_map m_pcell_ids;
|
pcell_name_map m_pcell_ids;
|
||||||
lib_proxy_map m_lib_proxy_map;
|
lib_proxy_map m_lib_proxy_map;
|
||||||
|
cold_proxy_map m_cold_proxy_map;
|
||||||
bool m_do_cleanup;
|
bool m_do_cleanup;
|
||||||
bool m_editable;
|
bool m_editable;
|
||||||
std::map<std::string, meta_info_name_id_type> m_meta_info_name_map;
|
std::map<std::string, meta_info_name_id_type> m_meta_info_name_map;
|
||||||
|
|
|
||||||
|
|
@ -221,14 +221,25 @@ LibraryProxy::update (db::ImportLayerMapping *layer_mapping)
|
||||||
real_lib = db::LibraryManager::instance ().lib (lp->lib_id ());
|
real_lib = db::LibraryManager::instance ().lib (lp->lib_id ());
|
||||||
}
|
}
|
||||||
|
|
||||||
inst.object ().cell_index (layout ()->get_lib_proxy (real_lib, real_cil));
|
|
||||||
|
|
||||||
ColdProxy *cp = dynamic_cast<ColdProxy *> (&real_lib->layout ().cell (real_cil));
|
ColdProxy *cp = dynamic_cast<ColdProxy *> (&real_lib->layout ().cell (real_cil));
|
||||||
if (cp) {
|
if (cp) {
|
||||||
|
|
||||||
// The final item is a cold proxy ("<defunct>" cell) - treat it like
|
// The final item is a cold proxy ("<defunct>" cell) - treat it like
|
||||||
// a library proxy as it may become one in the future, but replace it
|
// a library proxy as it may become one in the future, but replace it
|
||||||
// by a cold proxy now.
|
// by a cold proxy now.
|
||||||
layout ()->create_cold_proxy_as (cp->context_info (), inst.object ().cell_index ());
|
|
||||||
|
auto p = layout ()->find_cold_proxy (cp->context_info ());
|
||||||
|
if (p.first) {
|
||||||
|
// reuse existing proxy
|
||||||
|
inst.object ().cell_index (p.second);
|
||||||
|
} else {
|
||||||
|
// create a new proxy, reusing the first library proxy's replica
|
||||||
|
inst.object ().cell_index (layout ()->get_lib_proxy (real_lib, real_cil));
|
||||||
|
layout ()->create_cold_proxy_as (cp->context_info (), inst.object ().cell_index ());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
inst.object ().cell_index (layout ()->get_lib_proxy (real_lib, real_cil));
|
||||||
}
|
}
|
||||||
|
|
||||||
inst.transform_into (db::ICplxTrans (lib->layout ().dbu () / layout ()->dbu ()));
|
inst.transform_into (db::ICplxTrans (lib->layout ().dbu () / layout ()->dbu ()));
|
||||||
|
|
|
||||||
|
|
@ -129,12 +129,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Reimplemented from Cell: unregisters the proxy at the layout
|
* @brief Reimplemented from Cell: unregisters the proxy at the layout
|
||||||
*/
|
*/
|
||||||
void unregister ();
|
virtual void unregister ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reimplemented from Cell: reregisters the proxy at the layout
|
* @brief Reimplemented from Cell: reregisters the proxy at the layout
|
||||||
*/
|
*/
|
||||||
void reregister ();
|
virtual void reregister ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lib_id_type m_lib_id;
|
lib_id_type m_lib_id;
|
||||||
|
|
|
||||||
|
|
@ -773,8 +773,8 @@ TEST(7_monsterlib)
|
||||||
}
|
}
|
||||||
|
|
||||||
// as NOEX and NOEX2 are not present, a number of references are defunct (aka cold proxies)
|
// as NOEX and NOEX2 are not present, a number of references are defunct (aka cold proxies)
|
||||||
EXPECT_EQ (num_defunct (layout), size_t (15));
|
EXPECT_EQ (num_defunct (layout), size_t (6));
|
||||||
EXPECT_EQ (num_cells (layout), size_t (46));
|
EXPECT_EQ (num_cells (layout), size_t (25));
|
||||||
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
||||||
|
|
||||||
// NOTE: normalization would spoil the layout, so don't do it
|
// NOTE: normalization would spoil the layout, so don't do it
|
||||||
|
|
@ -794,7 +794,7 @@ TEST(7_monsterlib)
|
||||||
|
|
||||||
// all references now need to be resolved
|
// all references now need to be resolved
|
||||||
EXPECT_EQ (num_defunct (layout), size_t (0));
|
EXPECT_EQ (num_defunct (layout), size_t (0));
|
||||||
EXPECT_EQ (num_cells (layout), size_t (36));
|
EXPECT_EQ (num_cells (layout), size_t (25));
|
||||||
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
||||||
|
|
||||||
db::compare_layouts (_this, layout, tl::testsrc () + "/testdata/libman/design_au2.gds", db::NormalizationMode (db::NoNormalization | db::WithoutCellNames | db::AsPolygons));
|
db::compare_layouts (_this, layout, tl::testsrc () + "/testdata/libman/design_au2.gds", db::NormalizationMode (db::NoNormalization | db::WithoutCellNames | db::AsPolygons));
|
||||||
|
|
@ -807,7 +807,7 @@ TEST(7_monsterlib)
|
||||||
|
|
||||||
// all references now need to be resolved
|
// all references now need to be resolved
|
||||||
EXPECT_EQ (num_defunct (layout), size_t (0));
|
EXPECT_EQ (num_defunct (layout), size_t (0));
|
||||||
EXPECT_EQ (num_cells (layout), size_t (32));
|
EXPECT_EQ (num_cells (layout), size_t (25));
|
||||||
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
||||||
|
|
||||||
db::compare_layouts (_this, layout, tl::testsrc () + "/testdata/libman/design_au3.gds", db::NormalizationMode (db::NoNormalization | db::WithoutCellNames | db::AsPolygons));
|
db::compare_layouts (_this, layout, tl::testsrc () + "/testdata/libman/design_au3.gds", db::NormalizationMode (db::NoNormalization | db::WithoutCellNames | db::AsPolygons));
|
||||||
|
|
@ -816,8 +816,8 @@ TEST(7_monsterlib)
|
||||||
db::LibraryManager::instance ().delete_lib (lib_noex2);
|
db::LibraryManager::instance ().delete_lib (lib_noex2);
|
||||||
|
|
||||||
// after removing the libraries, we have defunct cells again
|
// after removing the libraries, we have defunct cells again
|
||||||
EXPECT_EQ (num_defunct (layout), size_t (11));
|
EXPECT_EQ (num_defunct (layout), size_t (6));
|
||||||
EXPECT_EQ (num_cells (layout), size_t (32));
|
EXPECT_EQ (num_cells (layout), size_t (25));
|
||||||
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
||||||
|
|
||||||
// but the layout did not change
|
// but the layout did not change
|
||||||
|
|
@ -827,8 +827,8 @@ TEST(7_monsterlib)
|
||||||
db::LibraryManager::instance ().delete_lib (lib_ex2);
|
db::LibraryManager::instance ().delete_lib (lib_ex2);
|
||||||
|
|
||||||
// after removing all libraries, we have even more defunct cells (i.e. all, except top)
|
// after removing all libraries, we have even more defunct cells (i.e. all, except top)
|
||||||
EXPECT_EQ (num_defunct (layout), size_t (19));
|
EXPECT_EQ (num_defunct (layout), size_t (12));
|
||||||
EXPECT_EQ (num_cells (layout), size_t (32));
|
EXPECT_EQ (num_cells (layout), size_t (25));
|
||||||
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
EXPECT_EQ (num_top_cells (layout), size_t (1));
|
||||||
|
|
||||||
// but the layout did not change
|
// but the layout did not change
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue