From 062567f206d6b5cdbea91a2336b5127af41b78dd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2026 19:41:19 +0200 Subject: [PATCH] WIP --- src/db/db/dbLibrary.cc | 39 +++++++++++++++++----- src/db/db/dbLibrary.h | 7 ++++ src/db/db/dbLibraryManager.cc | 20 +++++++++++- src/db/db/dbLibraryProxy.cc | 61 +++++++++++++++++------------------ 4 files changed, 86 insertions(+), 41 deletions(-) diff --git a/src/db/db/dbLibrary.cc b/src/db/db/dbLibrary.cc index 0f4470006..e3e4c353e 100644 --- a/src/db/db/dbLibrary.cc +++ b/src/db/db/dbLibrary.cc @@ -26,6 +26,7 @@ #include "dbPCellDeclaration.h" #include "dbPCellVariant.h" #include "dbLibraryManager.h" +#include "tlTimer.h" #include @@ -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 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 > pcells_to_map; std::vector 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 (&r->first->cell (*ci)); + db::LibraryProxy *lib_proxy = dynamic_cast (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 >::const_iterator lp = pcells_to_map.begin (); lp != pcells_to_map.end (); ++lp) { diff --git a/src/db/db/dbLibrary.h b/src/db/db/dbLibrary.h index b0883e788..05eef7bf9 100644 --- a/src/db/db/dbLibrary.h +++ b/src/db/db/dbLibrary.h @@ -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 * diff --git a/src/db/db/dbLibraryManager.cc b/src/db/db/dbLibraryManager.cc index e181855a3..304c27e9f 100644 --- a/src/db/db/dbLibraryManager.cc +++ b/src/db/db/dbLibraryManager.cc @@ -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 > libs; + libs.reserve (m_libs.size ()); + for (auto l = m_libs.begin (); l != m_libs.end (); ++l) { + libs.push_back (tl::weak_ptr (*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::iterator l = m_libs.begin (); l != m_libs.end (); ++l) { if (*l) { - (*l)->refresh (); + (*l)->layout ().restore_proxies (); } } } diff --git a/src/db/db/dbLibraryProxy.cc b/src/db/db/dbLibraryProxy.cc index 8a4e043f2..cd93e048c 100644 --- a/src/db/db/dbLibraryProxy.cc +++ b/src/db/db/dbLibraryProxy.cc @@ -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 (&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 (&real_lib->layout ().cell (real_cil)); + if (cp) { + // The final item is a cold proxy ("" 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); + } }