mirror of https://github.com/KLayout/klayout.git
Providing a (maybe faster, sometimes) backup implementation for cell mapping - to be used later maybe
This commit is contained in:
parent
c12942c5bc
commit
0067d46541
|
|
@ -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 ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue