Providing a (maybe faster, sometimes) backup implementation for cell mapping - to be used later maybe

This commit is contained in:
Matthias Koefferlein 2026-02-01 20:27:49 +01:00
parent c12942c5bc
commit 0067d46541
2 changed files with 132 additions and 42 deletions

View File

@ -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<db::ICplxTrans, db::trans_less_func<db::ICplxTrans> > trans_set_t;
typedef std::unordered_multiset<db::ICplxTrans> trans_set_t;
InstanceSetCompareFunction (const db::Layout &layout_a, db::cell_index_type initial_cell_a, const std::set<db::cell_index_type> *selection_cone_a, const db::Layout &layout_b, db::cell_index_type initial_cell_b, const std::set<db::cell_index_type> *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<unsigned int, db::ICplxTrans> &p) const
{
return tl::hcombine (p.first, tl::hfunc (p.second));
}
};
}
class InstanceSetCompareFunction
{
public:
typedef std::multiset<db::ICplxTrans, db::trans_less_func<db::ICplxTrans> > trans_set_t;
typedef std::unordered_multiset<std::pair<unsigned int, db::ICplxTrans>, InstanceSetCompareFunctionHash> trans_set_t;
InstanceSetCompareFunction (const db::Layout &layout_a, db::cell_index_type initial_cell_a, const std::set<db::cell_index_type> *selection_cone_a, const db::Layout &layout_b, db::cell_index_type initial_cell_b, const std::set<db::cell_index_type> *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<db::cell_index_type>::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<db::cell_index_type>::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<db::cell_index_type> *m_selection_cone_a; // TODO -> ptr @@@
const std::set<db::cell_index_type> *m_selection_cone_a;
const db::Layout &m_layout_b;
db::cell_index_type m_initial_cell_b;
const std::set<db::cell_index_type> *m_selection_cone_b; // TODO -> ptr @@@
std::map<db::cell_index_type, trans_set_t> m_tsa, m_tsb;
const std::set<db::cell_index_type> *m_selection_cone_b;
db::cell_index_type m_cell_a;
std::set<db::cell_index_type> m_callers_a;
trans_set_t m_trans;
std::map<db::cell_index_type, unsigned int> m_endpoints_a, m_endpoints_b;
unsigned int m_ep_index;
const trans_set_t &get_trans_set (std::map<db::cell_index_type, trans_set_t> &ts_cache, const db::Layout &layout, db::cell_index_type initial_cell, const std::set<db::cell_index_type> &selection, db::cell_index_type for_cell)
bool collect_or_compare_trans_set (bool collect,
trans_set_t &ts,
const std::map<db::cell_index_type, unsigned int> &endpoints,
const db::Layout &layout,
const std::set<db::cell_index_type> &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<db::cell_index_type, trans_set_t> &ts_cache, const db::Layout &layout, db::cell_index_type initial_cell, const std::set<db::cell_index_type> &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<db::cell_index_type> 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<size_t, db::cell_index_type> 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<size_t, db::cell_index_type> 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 <unsigned int, std::vector <db::cell_index_type> > b_group;
std::map <db::cell_index_type, unsigned int> b_group_of_cell;
std::map <db::cell_index_type, std::vector<db::cell_index_type> > new_candidates;
while (a != cm_a.end () && a->first == w) {
candidates.insert (std::make_pair (a->second, std::vector <db::cell_index_type> ()));
new_candidates.insert (std::make_pair (a->second, std::vector <db::cell_index_type> ()));
std::set <unsigned int> 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 <db::cell_index_type> ())).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 ());
}
}

View File

@ -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)