This commit is contained in:
Matthias Koefferlein 2026-03-29 19:41:19 +02:00
parent ddb261d708
commit 062567f206
4 changed files with 86 additions and 41 deletions

View File

@ -26,6 +26,7 @@
#include "dbPCellDeclaration.h"
#include "dbPCellVariant.h"
#include "dbLibraryManager.h"
#include "tlTimer.h"
#include <limits>
@ -166,14 +167,36 @@ Library::rename (const std::string &name)
void
Library::refresh ()
{
// save a copy of the layout, so we can refer to it
std::unique_ptr<db::Layout> org_layout (new db::Layout (layout ()));
refresh_without_restore ();
std::string name = reload ();
rename (name);
// proxies need to be restored in a special case when a library has a proxy to itself.
// The layout readers will not be able to create library references in this case.
layout ().restore_proxies ();
}
void
Library::refresh_without_restore ()
{
db::LibraryManager::instance ().unregister_lib (this);
try {
m_name = reload ();
} catch (...) {
// fallback - leave the library, but with empty layout
layout ().clear ();
db::LibraryManager::instance ().register_lib (this);
throw;
}
layout ().refresh ();
remap_to (this, org_layout.get ());
// re-register, potentially under the new name
db::LibraryManager::instance ().register_lib (this);
}
void
@ -198,9 +221,9 @@ Library::remap_to (db::Library *other, db::Layout *original_layout)
std::vector<std::pair<db::LibraryProxy *, db::PCellVariant *> > pcells_to_map;
std::vector<db::LibraryProxy *> lib_cells_to_map;
for (auto ci = r->first->begin_top_down (); ci != r->first->end_top_down (); ++ci) {
for (auto c = r->first->begin (); c != r->first->end (); ++c) {
db::LibraryProxy *lib_proxy = dynamic_cast<db::LibraryProxy *> (&r->first->cell (*ci));
db::LibraryProxy *lib_proxy = dynamic_cast<db::LibraryProxy *> (c.operator-> ());
if (lib_proxy && lib_proxy->lib_id () == get_id ()) {
db::Cell *lib_cell = &original_layout->cell (lib_proxy->library_cell_index ());
@ -217,7 +240,7 @@ Library::remap_to (db::Library *other, db::Layout *original_layout)
}
// We do PCell resolution before the library proxy resolution. The reason is that
// 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) {

View File

@ -225,6 +225,13 @@ public:
*/
void refresh ();
/**
* @brief Refreshes the library on all clients without restoring proxies
*
* This method is intended to be used internally for bulk refreshes.
*/
void refresh_without_restore ();
/**
* @brief Renames the library
*

View File

@ -284,9 +284,27 @@ LibraryManager::lib_internal (lib_id_type id) const
void
LibraryManager::refresh_all ()
{
// NOTE: libraries may get deleted during the refresh, so better use weak pointers here
// to track lifetime. Libraries appearing are not considered.
std::vector<tl::weak_ptr<Library> > libs;
libs.reserve (m_libs.size ());
for (auto l = m_libs.begin (); l != m_libs.end (); ++l) {
libs.push_back (tl::weak_ptr<Library> (*l));
}
for (auto l = libs.begin (); l != libs.end (); ++l) {
if (l->get ()) {
(*l)->refresh_without_restore ();
}
}
// restore proxies on all libraries - as the refresh happens in random order, dependencies
// are not necessarily resolved. This is done here.
for (std::vector<Library *>::iterator l = m_libs.begin (); l != m_libs.end (); ++l) {
if (*l) {
(*l)->refresh ();
(*l)->layout ().restore_proxies ();
}
}
}

View File

@ -22,6 +22,7 @@
#include "dbLibraryProxy.h"
#include "dbColdProxy.h"
#include "dbLibraryManager.h"
#include "dbLibrary.h"
#include "dbLayout.h"
@ -187,25 +188,6 @@ LibraryProxy::get_layer_indices (db::Layout &layout, db::ImportLayerMapping *lay
return m_layer_indices;
}
class LibraryCellIndexMapper
{
public:
LibraryCellIndexMapper (Layout &layout, Library *lib)
: mp_lib (lib), mp_layout (&layout)
{
// .. nothing yet ..
}
cell_index_type operator() (cell_index_type cell_index_in_lib)
{
return mp_layout->get_lib_proxy (mp_lib, cell_index_in_lib);
}
private:
Library *mp_lib;
Layout *mp_layout;
};
void
LibraryProxy::update (db::ImportLayerMapping *layer_mapping)
{
@ -215,29 +197,44 @@ LibraryProxy::update (db::ImportLayerMapping *layer_mapping)
Library *lib = LibraryManager::instance ().lib (lib_id ());
const db::Cell &source_cell = lib->layout ().cell (library_cell_index ());
db::ICplxTrans tr;
bool need_transform = false;
if (fabs (layout ()->dbu () - lib->layout ().dbu ()) > 1e-6) {
need_transform = true;
tr = db::ICplxTrans (lib->layout ().dbu () / layout ()->dbu ());
}
clear_shapes ();
clear_insts ();
for (unsigned int l = 0; l < lib->layout ().layers (); ++l) {
if (layer_indices [l] >= 0) {
shapes ((unsigned int) layer_indices [l]).assign_transformed (source_cell.shapes (l), tr);
shapes ((unsigned int) layer_indices [l]).assign_transformed (source_cell.shapes (l), db::ICplxTrans (lib->layout ().dbu () / layout ()->dbu ()));
}
}
LibraryCellIndexMapper cell_index_mapper (*layout (), lib);
for (Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) {
for (Cell::const_iterator inst = source_cell.begin (); !inst.at_end (); ++inst) {
db::Instance new_inst = insert (*inst, cell_index_mapper);
if (need_transform) {
replace (new_inst, new_inst.cell_inst ().transformed_into (tr));
db::CellInstArray inst = i->cell_inst ();
Library *real_lib = lib;
cell_index_type real_cil = inst.object ().cell_index ();
// use the "final lib", so we refer to the actual lib instead
// of building chains of lib references
LibraryProxy *lp;
while ((lp = dynamic_cast<LibraryProxy *> (&real_lib->layout ().cell (real_cil))) != 0) {
real_cil = lp->library_cell_index ();
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));
if (cp) {
// 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
// by a cold proxy now.
layout ()->create_cold_proxy_as (cp->context_info (), inst.object ().cell_index ());
}
inst.transform_into (db::ICplxTrans (lib->layout ().dbu () / layout ()->dbu ()));
insert (inst);
}
}