From 0067d46541161ea964114a4a86bc27796ef95307 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 1 Feb 2026 20:27:49 +0100 Subject: [PATCH] Providing a (maybe faster, sometimes) backup implementation for cell mapping - to be used later maybe --- src/db/db/dbCellMapping.cc | 172 ++++++++++++++++++++++++++++--------- src/db/db/dbLayerMapping.h | 2 +- 2 files changed, 132 insertions(+), 42 deletions(-) diff --git a/src/db/db/dbCellMapping.cc b/src/db/db/dbCellMapping.cc index d79732b4f..26d5770e5 100644 --- a/src/db/db/dbCellMapping.cc +++ b/src/db/db/dbCellMapping.cc @@ -25,6 +25,8 @@ #include "dbCellGraphUtils.h" #include "dbCellMapping.h" #include "dbLayoutUtils.h" +#include "dbCellInstanceSetHasher.h" +#include "dbHash.h" #include "tlLog.h" #include "tlTimer.h" @@ -122,11 +124,12 @@ private: // Some utility class: a compare function for a instance set of two cells in the context // of two layouts and two initial cells. -#if 0 -class InstanceSetCompareFunction +#if 1 + +class InstanceSetCompareFunction { public: - typedef std::multiset > trans_set_t; + typedef std::unordered_multiset trans_set_t; InstanceSetCompareFunction (const db::Layout &layout_a, db::cell_index_type initial_cell_a, const std::set *selection_cone_a, const db::Layout &layout_b, db::cell_index_type initial_cell_b, const std::set *selection_cone_b) : m_layout_a (layout_a), m_initial_cell_a (initial_cell_a), m_selection_cone_a (selection_cone_a), @@ -176,6 +179,11 @@ public: return trans.empty (); } + void make_endpoint (db::cell_index_type /*cell_a*/, db::cell_index_type /*cell_b*/) + { + // not supported by this version + } + private: const db::Layout &m_layout_a; db::cell_index_type m_initial_cell_a; @@ -258,73 +266,145 @@ private: } } }; + #else + +/* + * An alternative implementation of the InstanceSetCompareFunction + * + * This allows setting "endpoints" which are basically known cell identities + * and allow shortcutting the instance set comparison. They act as additional + * top cells. + * + * This implementation has a potential for higher performance, but + * in general it requires somewhat more memory and is not fully optimized yet. + */ + +namespace { + +struct InstanceSetCompareFunctionHash +{ + std::size_t operator () (const std::pair &p) const + { + return tl::hcombine (p.first, tl::hfunc (p.second)); + } +}; + +} + class InstanceSetCompareFunction { public: - typedef std::multiset > trans_set_t; + typedef std::unordered_multiset, InstanceSetCompareFunctionHash> trans_set_t; InstanceSetCompareFunction (const db::Layout &layout_a, db::cell_index_type initial_cell_a, const std::set *selection_cone_a, const db::Layout &layout_b, db::cell_index_type initial_cell_b, const std::set *selection_cone_b) - : m_layout_a (layout_a), m_initial_cell_a (initial_cell_a), m_selection_cone_a (selection_cone_a), - m_layout_b (layout_b), m_initial_cell_b (initial_cell_b), m_selection_cone_b (selection_cone_b) + : m_layout_a (layout_a), m_selection_cone_a (selection_cone_a), + m_layout_b (layout_b), m_selection_cone_b (selection_cone_b), + m_cell_a (std::numeric_limits::max ()), + m_ep_index (0) { - // .. + m_endpoints_a.insert (std::make_pair (initial_cell_a, m_ep_index)); + m_endpoints_b.insert (std::make_pair (initial_cell_b, m_ep_index)); + ++m_ep_index; } - // @@@ TODO: const method bool compare (db::cell_index_type cell_a, db::cell_index_type cell_b) { - return get_trans_set (m_tsa, m_layout_a, m_initial_cell_a, *m_selection_cone_a, cell_a) == get_trans_set (m_tsb, m_layout_b, m_initial_cell_b, *m_selection_cone_b, cell_b); + if (cell_a != m_cell_a) { + m_cell_a = cell_a; + m_trans.clear (); + collect_or_compare_trans_set (true, m_trans, m_endpoints_a, m_layout_a, *m_selection_cone_a, m_cell_a, db::ICplxTrans ()); + } + + trans_set_t trans (m_trans); + + double mag = m_layout_b.dbu () / m_layout_a.dbu (); + if (! collect_or_compare_trans_set (false, trans, m_endpoints_b, m_layout_b, *m_selection_cone_b, cell_b, db::ICplxTrans (mag))) { + return false; + } else { + return trans.empty (); + } + } + + void make_endpoint (db::cell_index_type cell_a, db::cell_index_type cell_b) + { + m_cell_a = std::numeric_limits::max (); + m_trans.clear (); + + m_endpoints_a.insert (std::make_pair (cell_a, m_ep_index)); + m_endpoints_b.insert (std::make_pair (cell_b, m_ep_index)); + ++m_ep_index; } private: const db::Layout &m_layout_a; - db::cell_index_type m_initial_cell_a; - const std::set *m_selection_cone_a; // TODO -> ptr @@@ + const std::set *m_selection_cone_a; const db::Layout &m_layout_b; - db::cell_index_type m_initial_cell_b; - const std::set *m_selection_cone_b; // TODO -> ptr @@@ - std::map m_tsa, m_tsb; + const std::set *m_selection_cone_b; + db::cell_index_type m_cell_a; + std::set m_callers_a; + trans_set_t m_trans; + std::map m_endpoints_a, m_endpoints_b; + unsigned int m_ep_index; - const trans_set_t &get_trans_set (std::map &ts_cache, const db::Layout &layout, db::cell_index_type initial_cell, const std::set &selection, db::cell_index_type for_cell) + bool collect_or_compare_trans_set (bool collect, + trans_set_t &ts, + const std::map &endpoints, + const db::Layout &layout, + const std::set &selection, + db::cell_index_type for_cell, + const db::ICplxTrans &child_trans) { - auto tsi = ts_cache.find (for_cell); - if (tsi == ts_cache.end ()) { - tsi = ts_cache.insert (std::make_pair (for_cell, trans_set_t ())).first; - get_trans_set_uncached (tsi->second, ts_cache, layout, initial_cell, selection, for_cell); - } - return tsi->second; - } + auto ep = endpoints.find (for_cell); + if (ep != endpoints.end ()) { + + auto key = std::make_pair (ep->second, child_trans); + + if (collect) { + ts.insert (key); + return true; + } else { + auto i = ts.find (key); + if (i == ts.end () || *i != key) { + return false; + } else { + ts.erase (i); + return true; + } + } - void get_trans_set_uncached (trans_set_t &ts, std::map &ts_cache, const db::Layout &layout, db::cell_index_type initial_cell, const std::set &selection, db::cell_index_type for_cell) - { - if (for_cell == initial_cell) { - ts.insert (db::ICplxTrans ()); - return; } - const db::Cell &c = layout.cell (for_cell); - for (auto p = c.begin_parent_insts (); ! p.at_end (); ++p) { + const db::Cell &fc = layout.cell (for_cell); + + std::set selected_parents; + for (auto p = fc.begin_parent_cells (); p != fc.end_parent_cells (); ++p) { + if (selection.find (*p) != selection.end ()) { + selected_parents.insert (*p); + } + } + + for (auto p = fc.begin_parent_insts (); ! p.at_end (); ++p) { - const db::CellInstArray &inst = p->child_inst ().cell_inst (); db::cell_index_type parent_cell = p->parent_cell_index (); + if (selected_parents.find (parent_cell) != selected_parents.end ()) { - if (selection.find (inst.object ().cell_index ()) != selection.end ()) { - - const trans_set_t &pts = get_trans_set (ts_cache, layout, initial_cell, selection, parent_cell); + const db::CellInstArray &inst = *p->basic_child_inst (); for (auto a = inst.begin (); ! a.at_end (); ++a) { auto ta = inst.complex_trans (*a); - for (auto pt = pts.begin (); pt != pts.end (); ++pt) { - ts.insert (*pt * ta); + if (! collect_or_compare_trans_set (collect, ts, endpoints, layout, selection, parent_cell, ta * child_trans)) { + return false; } - } } } + + return true; } }; + #endif // ------------------------------------------------------------------------------------- @@ -509,12 +589,12 @@ CellMapping::create_from_geometry (const db::Layout &layout_a, db::cell_index_ty db::CellCounter cc_b (&layout_b, cell_index_b); std::multimap cm_b; - for (db::CellCounter::selection_iterator c = cc_b.begin (); c != cc_b.end (); ++c) { + for (auto c = cc_b.begin (); c != cc_b.end (); ++c) { cm_b.insert (std::make_pair (*c == cell_index_b ? 0 : cc_b.weight (*c), *c)); } std::multimap cm_a; - for (db::CellCounter::selection_iterator c = cc_a.begin (); c != cc_a.end (); ++c) { + for (auto c = cc_a.begin (); c != cc_a.end (); ++c) { cm_a.insert (std::make_pair (*c == cell_index_a ? 0 : cc_a.weight (*c), *c)); } @@ -551,10 +631,11 @@ CellMapping::create_from_geometry (const db::Layout &layout_a, db::cell_index_ty unsigned int g = 0; std::map > b_group; std::map b_group_of_cell; + std::map > new_candidates; while (a != cm_a.end () && a->first == w) { - candidates.insert (std::make_pair (a->second, std::vector ())); + new_candidates.insert (std::make_pair (a->second, std::vector ())); std::set groups_taken; @@ -566,7 +647,7 @@ CellMapping::create_from_geometry (const db::Layout &layout_a, db::cell_index_ty if (groups_taken.find (bg->second) == groups_taken.end ()) { if (cmp.compare (a->second, bb->second)) { - candidates [a->second] = b_group [bg->second]; + new_candidates [a->second] = b_group [bg->second]; groups_taken.insert (bg->second); } } @@ -574,7 +655,7 @@ CellMapping::create_from_geometry (const db::Layout &layout_a, db::cell_index_ty } else { if (cmp.compare (a->second, bb->second)) { - candidates [a->second].push_back (bb->second); + new_candidates [a->second].push_back (bb->second); b_group_of_cell.insert (std::make_pair (bb->second, g)); b_group.insert (std::make_pair (g, std::vector ())).first->second.push_back (bb->second); } @@ -598,6 +679,15 @@ CellMapping::create_from_geometry (const db::Layout &layout_a, db::cell_index_ty ++b; } + for (auto c = new_candidates.begin (); c != new_candidates.end (); ++c) { + if (c->second.size () == 1) { + // a single candidate: establish as new endpoint for the comparer + cmp.make_endpoint (c->first, c->second.front ()); + } + } + + candidates.insert (new_candidates.begin (), new_candidates.end ()); + } } diff --git a/src/db/db/dbLayerMapping.h b/src/db/db/dbLayerMapping.h index 9b4c34484..4a01eebcb 100644 --- a/src/db/db/dbLayerMapping.h +++ b/src/db/db/dbLayerMapping.h @@ -97,7 +97,7 @@ public: /** * @brief Add a layer mapping * - * @param layer_b The index of the layer in layout_a (the source of the mapping) + * @param layer_b The index of the layer in layout_b (the source of the mapping) * @param layer_a The index of the layer in layout_a (the target of the mapping) */ void map (unsigned int layer_b, unsigned int layer_a)