WIP: some performance improvements, cronology debugging support (experimental)

This commit is contained in:
Matthias Koefferlein 2018-11-03 12:28:27 +01:00
parent 62224b0d91
commit 17f53cf54e
6 changed files with 277 additions and 90 deletions

View File

@ -97,6 +97,12 @@ equals(HAVE_RUBY, "1") {
} }
} }
equals(HAVE_CRONOLOGY, "1") {
DEFINES += HAVE_CRONOLOGY
LIBS += $$CRONOLOGY_LIB
INCLUDEPATH += $$CRONOLOGY_INCLUDE
}
msvc { msvc {
QMAKE_CXXFLAGS += \ QMAKE_CXXFLAGS += \

View File

@ -31,6 +31,33 @@
#include "tlTimer.h" #include "tlTimer.h"
#include "tlInternational.h" #include "tlInternational.h"
// ---------------------------------------------------------------------------------------------
// Cronology debugging support (TODO: experimental)
#if defined(HAVE_CRONOLOGY)
#include <cronology/events.hpp>
CRONOLOGY_MAKE_EVENT(event_compute_contexts, "Compute contexts")
CRONOLOGY_MAKE_EVENT(event_compute_contexts_unlocked, "Compute contexts (unlocked)")
cronology::events::event_collection<event_compute_contexts, event_compute_contexts_unlocked> collect_events;
#define CRONOLOGY_COLLECTION_BRACKET(event_name) cronology::EventBracket __bracket##event_name (collect_events.threadwise ()->event<event_name> ().event ());
CRONOLOGY_MAKE_EVENT(event_compute_results, "Compute results")
CRONOLOGY_MAKE_EVENT(event_compute_local_cell, "Compute local cell results")
CRONOLOGY_MAKE_EVENT(event_propagate, "Propagate local cell results")
cronology::events::event_collection<event_compute_results, event_compute_local_cell, event_propagate> compute_events;
#define CRONOLOGY_COMPUTE_BRACKET(event_name) cronology::EventBracket __bracket##event_name (compute_events.threadwise ()->event<event_name> ().event ());
#else
#define CRONOLOGY_COLLECTION_BRACKET(event_name)
#define CRONOLOGY_COMPUTE_BRACKET(event_name)
#endif
namespace db namespace db
{ {
@ -42,6 +69,7 @@ class shape_reference_translator
{ {
public: public:
typedef typename Ref::shape_type shape_type; typedef typename Ref::shape_type shape_type;
typedef typename Ref::trans_type ref_trans_type;
shape_reference_translator (db::Layout *target_layout) shape_reference_translator (db::Layout *target_layout)
: mp_layout (target_layout) : mp_layout (target_layout)
@ -51,21 +79,102 @@ public:
Ref operator() (const Ref &ref) const Ref operator() (const Ref &ref) const
{ {
tl::MutexLocker locker (&mp_layout->lock ()); typename std::unordered_map<const shape_type *, const shape_type *>::const_iterator m = m_cache.find (ref.ptr ());
shape_type sh = ref.obj ().transformed (ref.trans ()); if (m != m_cache.end ()) {
return Ref (sh, mp_layout->shape_repository ());
return Ref (m->second, ref.trans ());
} else {
const shape_type *ptr;
{
tl::MutexLocker locker (&mp_layout->lock ());
ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (ref.obj ());
}
m_cache[ref.ptr ()] = ptr;
return Ref (ptr, ref.trans ());
}
} }
template <class Trans> template <class Trans>
Ref operator() (const Ref &ref, const Trans &tr) const Ref operator() (const Ref &ref, const Trans &tr) const
{ {
tl::MutexLocker locker (&mp_layout->lock ()); shape_type sh = ref.obj ().transformed (Trans (ref_trans_type (tr).inverted ()) * tr);
shape_type sh = ref.obj ().transformed (tr * Trans (ref.trans ())); ref_trans_type red_trans;
return Ref (sh, mp_layout->shape_repository ()); sh.reduce (red_trans);
typename std::unordered_map<shape_type, std::pair<const shape_type *, ref_trans_type> >::const_iterator m = m_cache_by_shape.find (sh);
if (m != m_cache_by_shape.end ()) {
return Ref (m->second.first, ref_trans_type (tr * Trans (ref.trans ())) * m->second.second);
} else {
const shape_type *ptr;
{
tl::MutexLocker locker (&mp_layout->lock ());
ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh);
}
m_cache_by_shape[sh] = std::make_pair (ptr, red_trans);
return Ref (ptr, ref_trans_type (tr * Trans (ref.trans ())) * red_trans);
}
} }
private: private:
db::Layout *mp_layout; db::Layout *mp_layout;
mutable std::unordered_map<const shape_type *, const shape_type *> m_cache;
mutable std::unordered_map<shape_type, std::pair<const shape_type *, ref_trans_type> > m_cache_by_shape;
};
template <class Ref, class Trans>
class shape_reference_translator_with_trans
{
public:
typedef typename Ref::shape_type shape_type;
typedef typename Ref::trans_type ref_trans_type;
shape_reference_translator_with_trans (db::Layout *target_layout, const Trans &trans)
: mp_layout (target_layout), m_trans (trans), m_ref_trans (trans), m_bare_trans (Trans (m_ref_trans.inverted ()) * trans)
{
// .. nothing yet ..
}
Ref operator() (const Ref &ref) const
{
typename std::unordered_map<const shape_type *, std::pair<const shape_type *, ref_trans_type> >::const_iterator m = m_cache.find (ref.ptr ());
if (m != m_cache.end ()) {
return Ref (m->second.first, ref_trans_type (m_trans * Trans (ref.trans ())) * m->second.second);
} else {
shape_type sh = ref.obj ().transformed (m_bare_trans);
ref_trans_type red_trans;
sh.reduce (red_trans);
const shape_type *ptr;
{
tl::MutexLocker locker (&mp_layout->lock ());
ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh);
}
m_cache[ref.ptr ()] = std::make_pair (ptr, red_trans);
return Ref (ptr, ref_trans_type (m_trans * Trans (ref.trans ())) * red_trans);
}
}
private:
db::Layout *mp_layout;
Trans m_trans;
ref_trans_type m_ref_trans;
Trans m_bare_trans;
mutable std::unordered_map<const shape_type *, std::pair<const shape_type *, ref_trans_type> > m_cache;
}; };
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
@ -83,7 +192,7 @@ LocalProcessorCellContext::add (db::LocalProcessorCellContext *parent_context, d
} }
void void
LocalProcessorCellContext::propagate (const std::set<db::PolygonRef> &res) LocalProcessorCellContext::propagate (const std::unordered_set<db::PolygonRef> &res)
{ {
if (res.empty ()) { if (res.empty ()) {
return; return;
@ -95,13 +204,19 @@ LocalProcessorCellContext::propagate (const std::set<db::PolygonRef> &res)
tl_assert (d->parent != 0); tl_assert (d->parent != 0);
db::Layout *subject_layout = d->parent->layout (); db::Layout *subject_layout = d->parent->layout ();
shape_reference_translator<db::PolygonRef> rt (subject_layout); shape_reference_translator_with_trans<db::PolygonRef, db::ICplxTrans> rt (subject_layout, d->cell_inst);
for (std::set<db::PolygonRef>::const_iterator r = res.begin (); r != res.end (); ++r) { std::vector<db::PolygonRef> new_refs;
d->parent_context->propagated ().insert (rt (*r, d->cell_inst)); new_refs.reserve (res.size ());
for (std::unordered_set<db::PolygonRef>::const_iterator r = res.begin (); r != res.end (); ++r) {
new_refs.push_back (rt (*r));
}
{
tl::MutexLocker locker (&d->parent_context->lock ());
d->parent_context->propagated ().insert (new_refs.begin (), new_refs.end ());
} }
} }
} }
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
@ -122,7 +237,7 @@ LocalProcessorCellContexts::LocalProcessorCellContexts (const db::Cell *intruder
db::LocalProcessorCellContext * db::LocalProcessorCellContext *
LocalProcessorCellContexts::find_context (const key_type &intruders) LocalProcessorCellContexts::find_context (const key_type &intruders)
{ {
std::map<key_type, db::LocalProcessorCellContext>::iterator c = m_contexts.find (intruders); std::unordered_map<key_type, db::LocalProcessorCellContext>::iterator c = m_contexts.find (intruders);
return c != m_contexts.end () ? &c->second : 0; return c != m_contexts.end () ? &c->second : 0;
} }
@ -135,12 +250,14 @@ LocalProcessorCellContexts::create (const key_type &intruders)
void void
LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, unsigned int output_layer, const LocalProcessor *proc) LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, unsigned int output_layer, const LocalProcessor *proc)
{ {
CRONOLOGY_COMPUTE_BRACKET(event_compute_results)
bool first = true; bool first = true;
std::set<db::PolygonRef> common; std::unordered_set<db::PolygonRef> common;
int index = 0; int index = 0;
int total = int (m_contexts.size ()); int total = int (m_contexts.size ());
for (std::map<key_type, db::LocalProcessorCellContext>::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { for (std::unordered_map<key_type, db::LocalProcessorCellContext>::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) {
++index; ++index;
@ -151,54 +268,68 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte
if (first) { if (first) {
{ {
tl::MutexLocker locker (&contexts.lock ()); tl::MutexLocker locker (&c->second.lock ());
common = c->second.propagated (); common = c->second.propagated ();
} }
CRONOLOGY_COMPUTE_BRACKET(event_compute_local_cell)
proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, common); proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, common);
first = false; first = false;
} else { } else {
std::set<db::PolygonRef> res; std::unordered_set<db::PolygonRef> res;
{ {
tl::MutexLocker locker (&contexts.lock ()); tl::MutexLocker locker (&c->second.lock ());
res = c->second.propagated (); res = c->second.propagated ();
} }
proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, res); {
CRONOLOGY_COMPUTE_BRACKET(event_compute_local_cell)
proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, res);
}
if (common.empty ()) { if (common.empty ()) {
tl::MutexLocker locker (&contexts.lock ()); CRONOLOGY_COMPUTE_BRACKET(event_propagate)
c->second.propagate (res); c->second.propagate (res);
} else if (res != common) { } else if (res != common) {
std::set<db::PolygonRef> lost; CRONOLOGY_COMPUTE_BRACKET(event_propagate)
std::set_difference (common.begin (), common.end (), res.begin (), res.end (), std::inserter (lost, lost.end ()));
std::unordered_set<db::PolygonRef> lost;
for (std::unordered_set<db::PolygonRef>::const_iterator i = common.begin (); i != common.end (); ++i) {
if (res.find (*i) == res.end ()) {
lost.insert (*i);
}
}
if (! lost.empty ()) { if (! lost.empty ()) {
std::set<db::PolygonRef> new_common; std::unordered_set<db::PolygonRef> new_common;
std::set_intersection (common.begin (), common.end (), res.begin (), res.end (), std::inserter (new_common, new_common.end ())); for (std::unordered_set<db::PolygonRef>::const_iterator i = common.begin (); i != common.end (); ++i) {
if (res.find (*i) != res.end ()) {
new_common.insert (*i);
}
}
common.swap (new_common); common.swap (new_common);
for (std::map<key_type, db::LocalProcessorCellContext>::iterator cc = m_contexts.begin (); cc != c; ++cc) { for (std::unordered_map<key_type, db::LocalProcessorCellContext>::iterator cc = m_contexts.begin (); cc != c; ++cc) {
tl::MutexLocker locker (&contexts.lock ());
cc->second.propagate (lost); cc->second.propagate (lost);
} }
} }
std::set<db::PolygonRef> gained; std::unordered_set<db::PolygonRef> gained;
std::set_difference (res.begin (), res.end (), common.begin (), common.end (), std::inserter (gained, gained.end ())); for (std::unordered_set<db::PolygonRef>::const_iterator i = res.begin (); i != res.end (); ++i) {
if (common.find (*i) == common.end ()) {
{ gained.insert (*i);
tl::MutexLocker locker (&contexts.lock ()); }
c->second.propagate (gained);
} }
c->second.propagate (gained);
} }
} }
@ -256,7 +387,7 @@ ShapeInteractions::intruders_for (unsigned int subject_id) const
const db::PolygonRef & const db::PolygonRef &
ShapeInteractions::shape (unsigned int id) const ShapeInteractions::shape (unsigned int id) const
{ {
std::map<unsigned int, db::PolygonRef>::const_iterator i = m_shapes.find (id); std::unordered_map<unsigned int, db::PolygonRef>::const_iterator i = m_shapes.find (id);
if (i == m_shapes.end ()) { if (i == m_shapes.end ()) {
static db::PolygonRef s; static db::PolygonRef s;
return s; return s;
@ -363,7 +494,7 @@ private:
unsigned int m_intruder_layer; unsigned int m_intruder_layer;
db::Coord m_dist; db::Coord m_dist;
ShapeInteractions *mp_result; ShapeInteractions *mp_result;
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int> m_inst_shape_ids; std::unordered_map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int> m_inst_shape_ids;
void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int inst_id, const db::Box &region) void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int inst_id, const db::Box &region)
{ {
@ -380,7 +511,7 @@ private:
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on // reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
// the intruder side. // the intruder side.
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2)); std::unordered_map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2));
if (k == m_inst_shape_ids.end ()) { if (k == m_inst_shape_ids.end ()) {
k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first; k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first;
@ -408,7 +539,7 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u
const db::Cell &cell2 = layout2->cell (inst2->object ().cell_index ()); const db::Cell &cell2 = layout2->cell (inst2->object ().cell_index ());
db::box_convert <db::CellInst, true> inst2_bc (*layout2, layer2); db::box_convert <db::CellInst, true> inst2_bc (*layout2, layer2);
std::set<db::ICplxTrans> relative_trans_seen; std::unordered_set<db::ICplxTrans> relative_trans_seen;
for (db::CellInstArray::iterator n = inst1->begin (); ! n.at_end (); ++n) { for (db::CellInstArray::iterator n = inst1->begin (); ! n.at_end (); ++n) {
@ -465,9 +596,9 @@ struct InteractionRegistrationInst2Inst
: db::box_scanner_receiver2<db::CellInstArray, unsigned int, db::CellInstArray, unsigned int> : db::box_scanner_receiver2<db::CellInstArray, unsigned int, db::CellInstArray, unsigned int>
{ {
public: public:
typedef std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > interaction_value_type; typedef std::pair<std::unordered_set<const db::CellInstArray *>, std::unordered_set<db::PolygonRef> > interaction_value_type;
InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::map<const db::CellInstArray *, interaction_value_type> *result) InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::unordered_map<const db::CellInstArray *, interaction_value_type> *result)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result) : mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result)
{ {
// nothing yet .. // nothing yet ..
@ -500,8 +631,8 @@ private:
const db::Layout *mp_subject_layout, *mp_intruder_layout; const db::Layout *mp_subject_layout, *mp_intruder_layout;
unsigned int m_subject_layer, m_intruder_layer; unsigned int m_subject_layer, m_intruder_layer;
db::Coord m_dist; db::Coord m_dist;
std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *mp_result; std::unordered_map<const db::CellInstArray *, std::pair<std::unordered_set<const db::CellInstArray *>, std::unordered_set<db::PolygonRef> > > *mp_result;
std::set<std::pair<unsigned int, unsigned int> > m_interactions; std::unordered_set<std::pair<unsigned int, unsigned int> > m_interactions;
}; };
static bool static bool
@ -537,7 +668,7 @@ struct InteractionRegistrationInst2Shape
: db::box_scanner_receiver2<db::CellInstArray, unsigned int, db::PolygonRef, unsigned int> : db::box_scanner_receiver2<db::CellInstArray, unsigned int, db::PolygonRef, unsigned int>
{ {
public: public:
InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *result) InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, std::unordered_map<const db::CellInstArray *, std::pair<std::unordered_set<const db::CellInstArray *>, std::unordered_set<db::PolygonRef> > > *result)
: mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result) : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result)
{ {
// nothing yet .. // nothing yet ..
@ -554,7 +685,7 @@ private:
const db::Layout *mp_subject_layout; const db::Layout *mp_subject_layout;
unsigned int m_subject_layer; unsigned int m_subject_layer;
db::Coord m_dist; db::Coord m_dist;
std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *mp_result; std::unordered_map<const db::CellInstArray *, std::pair<std::unordered_set<const db::CellInstArray *>, std::unordered_set<db::PolygonRef> > > *mp_result;
}; };
} }
@ -562,7 +693,7 @@ private:
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
// LocalProcessorContextComputationTask implementation // LocalProcessorContextComputationTask implementation
LocalProcessorContextComputationTask::LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist) LocalProcessorContextComputationTask::LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders, db::Coord dist)
: tl::Task (), : tl::Task (),
mp_proc (proc), mp_contexts (&contexts), mp_parent_context (parent_context), mp_proc (proc), mp_contexts (&contexts), mp_parent_context (parent_context),
mp_subject_parent (subject_parent), mp_subject_cell (subject_cell), m_subject_cell_inst (subject_cell_inst), mp_subject_parent (subject_parent), mp_subject_cell (subject_cell), m_subject_cell_inst (subject_cell_inst),
@ -630,7 +761,7 @@ void LocalProcessor::run (LocalOperation *op, unsigned int subject_layer, unsign
compute_results (contexts, op, output_layer); compute_results (contexts, op, output_layer);
} }
void LocalProcessor::push_results (db::Cell *cell, unsigned int output_layer, const std::set<db::PolygonRef> &result) const void LocalProcessor::push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<db::PolygonRef> &result) const
{ {
if (! result.empty ()) { if (! result.empty ()) {
tl::MutexLocker locker (&cell->layout ()->lock ()); tl::MutexLocker locker (&cell->layout ()->lock ());
@ -654,7 +785,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const L
contexts.set_intruder_layer (intruder_layer); contexts.set_intruder_layer (intruder_layer);
contexts.set_subject_layer (subject_layer); contexts.set_subject_layer (subject_layer);
std::pair<std::set<db::CellInstArray>, std::set<db::PolygonRef> > intruders; std::pair<std::unordered_set<db::CellInstArray>, std::unordered_set<db::PolygonRef> > intruders;
issue_compute_contexts (contexts, 0, 0, mp_subject_top, db::ICplxTrans (), mp_intruder_top, intruders, op->dist ()); issue_compute_contexts (contexts, 0, 0, mp_subject_top, db::ICplxTrans (), mp_intruder_top, intruders, op->dist ());
if (mp_cc_job.get ()) { if (mp_cc_job.get ()) {
@ -674,7 +805,7 @@ void LocalProcessor::issue_compute_contexts (LocalProcessorContexts &contexts,
db::Cell *subject_cell, db::Cell *subject_cell,
const db::ICplxTrans &subject_cell_inst, const db::ICplxTrans &subject_cell_inst,
const db::Cell *intruder_cell, const db::Cell *intruder_cell,
std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders,
db::Coord dist) const db::Coord dist) const
{ {
bool is_small_job = subject_cell->begin ().at_end (); bool is_small_job = subject_cell->begin ().at_end ();
@ -692,9 +823,11 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
db::Cell *subject_cell, db::Cell *subject_cell,
const db::ICplxTrans &subject_cell_inst, const db::ICplxTrans &subject_cell_inst,
const db::Cell *intruder_cell, const db::Cell *intruder_cell,
const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, const std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders,
db::Coord dist) const db::Coord dist) const
{ {
CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts)
if (tl::verbosity () >= 30) { if (tl::verbosity () >= 30) {
if (! subject_parent) { if (! subject_parent) {
tl::log << tr ("Computing context for top cell ") << mp_subject_layout->cell_name (subject_cell->cell_index ()); tl::log << tr ("Computing context for top cell ") << mp_subject_layout->cell_name (subject_cell->cell_index ());
@ -726,6 +859,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
// perform the actual task .. // perform the actual task ..
CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts_unlocked)
const db::Shapes *intruder_shapes = 0; const db::Shapes *intruder_shapes = 0;
if (intruder_cell) { if (intruder_cell) {
intruder_shapes = &intruder_cell->shapes (contexts.intruder_layer ()); intruder_shapes = &intruder_cell->shapes (contexts.intruder_layer ());
@ -740,9 +874,9 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
if (! subject_cell->begin ().at_end ()) { if (! subject_cell->begin ().at_end ()) {
typedef std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > interaction_value_type; typedef std::pair<std::unordered_set<const db::CellInstArray *>, std::unordered_set<db::PolygonRef> > interaction_value_type;
std::map<const db::CellInstArray *, interaction_value_type> interactions; std::unordered_map<const db::CellInstArray *, interaction_value_type> interactions;
// insert dummy interactions to handle at least the child cell vs. itself // insert dummy interactions to handle at least the child cell vs. itself
// - this is important so we will always handle the instances unless they are // - this is important so we will always handle the instances unless they are
@ -792,7 +926,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
} }
for (std::set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { for (std::unordered_set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) {
if (! inst_bci (*i).empty ()) { if (! inst_bci (*i).empty ()) {
scanner.insert2 (i.operator-> (), ++id); scanner.insert2 (i.operator-> (), ++id);
} }
@ -811,7 +945,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
} }
} }
for (std::set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { for (std::unordered_set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
scanner.insert2 (i.operator-> (), 0); scanner.insert2 (i.operator-> (), 0);
} }
@ -824,10 +958,9 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
scanner.process (rec, dist, inst_bcs, db::box_convert<db::PolygonRef> ()); scanner.process (rec, dist, inst_bcs, db::box_convert<db::PolygonRef> ());
} }
for (std::map<const db::CellInstArray *, interaction_value_type>::const_iterator i = interactions.begin (); i != interactions.end (); ++i) { for (std::unordered_map<const db::CellInstArray *, interaction_value_type>::const_iterator i = interactions.begin (); i != interactions.end (); ++i) {
db::Cell &subject_child_cell = mp_subject_layout->cell (i->first->object ().cell_index ()); db::Cell &subject_child_cell = mp_subject_layout->cell (i->first->object ().cell_index ());
db::shape_reference_translator<db::PolygonRef> rt (mp_subject_layout);
for (db::CellInstArray::iterator n = i->first->begin (); ! n.at_end (); ++n) { for (db::CellInstArray::iterator n = i->first->begin (); ! n.at_end (); ++n) {
@ -837,17 +970,19 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
if (! nbox.empty ()) { if (! nbox.empty ()) {
std::pair<std::set<db::CellInstArray>, std::set<db::PolygonRef> > intruders_below; std::pair<std::unordered_set<db::CellInstArray>, std::unordered_set<db::PolygonRef> > intruders_below;
for (std::set<db::PolygonRef>::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) { db::shape_reference_translator_with_trans<db::PolygonRef, db::ICplxTrans> rt (mp_subject_layout, tni);
for (std::unordered_set<db::PolygonRef>::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) {
if (nbox.overlaps (p->box ())) { if (nbox.overlaps (p->box ())) {
intruders_below.second.insert (rt (*p, tni)); intruders_below.second.insert (rt (*p));
} }
} }
// TODO: in some cases, it may be possible to optimize this for arrays // TODO: in some cases, it may be possible to optimize this for arrays
for (std::set<const db::CellInstArray *>::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) { for (std::unordered_set<const db::CellInstArray *>::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) {
for (db::CellInstArray::iterator k = (*j)->begin_touching (nbox.enlarged (db::Vector (-1, -1)), inst_bcii); ! k.at_end (); ++k) { for (db::CellInstArray::iterator k = (*j)->begin_touching (nbox.enlarged (db::Vector (-1, -1)), inst_bcii); ! k.at_end (); ++k) {
db::ICplxTrans tk = (*j)->complex_trans (*k); db::ICplxTrans tk = (*j)->complex_trans (*k);
// NOTE: no self-interactions // NOTE: no self-interactions
@ -899,7 +1034,7 @@ LocalProcessor::compute_results (LocalProcessorContexts &contexts, const LocalOp
tl::SelfTimer timer (tl::verbosity () >= 21, tl::sprintf (tl::to_string (tr ("Computing results iteration #%d")), iter)); tl::SelfTimer timer (tl::verbosity () >= 21, tl::sprintf (tl::to_string (tr ("Computing results iteration #%d")), iter));
bool any = false; bool any = false;
std::set<db::cell_index_type> later; std::unordered_set<db::cell_index_type> later;
std::vector<db::cell_index_type> next_cells_bu; std::vector<db::cell_index_type> next_cells_bu;
next_cells_bu.reserve (cells_bu.size ()); next_cells_bu.reserve (cells_bu.size ());
@ -954,7 +1089,7 @@ LocalProcessor::compute_results (LocalProcessorContexts &contexts, const LocalOp
} }
void void
LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const db::LocalOperation *op, const std::pair<std::set<CellInstArray>, std::set<db::PolygonRef> > &intruders, std::set<db::PolygonRef> &result) const LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const db::LocalOperation *op, const std::pair<std::unordered_set<CellInstArray>, std::unordered_set<db::PolygonRef> > &intruders, std::unordered_set<db::PolygonRef> &result) const
{ {
const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ()); const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ());
@ -1001,7 +1136,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
scanner.insert (ref, id++); scanner.insert (ref, id++);
} }
for (std::set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { for (std::unordered_set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
scanner.insert (i.operator-> (), interactions.next_id ()); scanner.insert (i.operator-> (), interactions.next_id ());
} }
@ -1018,7 +1153,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
scanner.insert1 (ref, id++); scanner.insert1 (ref, id++);
} }
for (std::set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { for (std::unordered_set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
scanner.insert2 (i.operator-> (), interactions.next_id ()); scanner.insert2 (i.operator-> (), interactions.next_id ());
} }
@ -1060,7 +1195,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
} }
} }
for (std::set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { for (std::unordered_set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) {
if (! inst_bci (*i).empty ()) { if (! inst_bci (*i).empty ()) {
scanner.insert2 (i.operator-> (), ++inst_id); scanner.insert2 (i.operator-> (), ++inst_id);
} }

View File

@ -33,6 +33,46 @@
#include <map> #include <map>
#include <set> #include <set>
#include <vector> #include <vector>
#include <unordered_map>
#include <unordered_set>
// @@@ should go into dbHash.h
#include "dbHash.h"
namespace std
{
template <class C>
struct hash <db::disp_trans<C> >
{
size_t operator() (const db::disp_trans<C> &t) const
{
return hfunc (t.disp ());
}
};
template <class Polygon, class Trans>
struct hash<db::polygon_ref<Polygon, Trans> >
{
size_t operator() (const db::polygon_ref<Polygon, Trans> &o) const
{
return hfunc (size_t (o.ptr ()), std::hash<Trans> () (o.trans ()));
}
};
template <class T>
struct hash<std::unordered_set<T> >
{
size_t operator() (const std::unordered_set<T> &o) const
{
size_t hf = 0;
for (typename std::unordered_set<T>::const_iterator i = o.begin (); i != o.end (); ++i) {
hf = hfunc (hf, std::hash <T> () (*i));
}
return hf;
}
};
}
namespace db namespace db
{ {
@ -45,7 +85,7 @@ class LocalProcessorContexts;
class DB_PLUGIN_PUBLIC ShapeInteractions class DB_PLUGIN_PUBLIC ShapeInteractions
{ {
public: public:
typedef std::map<unsigned int, std::vector<unsigned int> > container; typedef std::unordered_map<unsigned int, std::vector<unsigned int> > container;
typedef container::const_iterator iterator; typedef container::const_iterator iterator;
typedef container::value_type::second_type::const_iterator iterator2; typedef container::value_type::second_type::const_iterator iterator2;
@ -74,8 +114,8 @@ public:
} }
private: private:
std::map<unsigned int, std::vector<unsigned int> > m_interactions; std::unordered_map<unsigned int, std::vector<unsigned int> > m_interactions;
std::map<unsigned int, db::PolygonRef> m_shapes; std::unordered_map<unsigned int, db::PolygonRef> m_shapes;
unsigned int m_id; unsigned int m_id;
}; };
@ -102,14 +142,14 @@ public:
LocalProcessorCellContext (); LocalProcessorCellContext ();
void add (db::LocalProcessorCellContext *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst); void add (db::LocalProcessorCellContext *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst);
void propagate (const std::set<db::PolygonRef> &res); void propagate (const std::unordered_set<db::PolygonRef> &res);
std::set<db::PolygonRef> &propagated () std::unordered_set<db::PolygonRef> &propagated ()
{ {
return m_propagated; return m_propagated;
} }
const std::set<db::PolygonRef> &propagated () const const std::unordered_set<db::PolygonRef> &propagated () const
{ {
return m_propagated; return m_propagated;
} }
@ -119,16 +159,22 @@ public:
return m_drops.size (); return m_drops.size ();
} }
tl::Mutex &lock ()
{
return m_lock;
}
private: private:
std::set<db::PolygonRef> m_propagated; std::unordered_set<db::PolygonRef> m_propagated;
std::vector<LocalProcessorCellDrop> m_drops; std::vector<LocalProcessorCellDrop> m_drops;
tl::Mutex m_lock;
}; };
class DB_PLUGIN_PUBLIC LocalProcessorCellContexts class DB_PLUGIN_PUBLIC LocalProcessorCellContexts
{ {
public: public:
typedef std::pair<std::set<CellInstArray>, std::set<db::PolygonRef> > key_type; typedef std::pair<std::unordered_set<CellInstArray>, std::unordered_set<db::PolygonRef> > key_type;
typedef std::map<key_type, db::LocalProcessorCellContext> map_type; typedef std::unordered_map<key_type, db::LocalProcessorCellContext> map_type;
typedef map_type::const_iterator iterator; typedef map_type::const_iterator iterator;
LocalProcessorCellContexts (); LocalProcessorCellContexts ();
@ -150,13 +196,13 @@ public:
private: private:
const db::Cell *mp_intruder_cell; const db::Cell *mp_intruder_cell;
std::map<key_type, db::LocalProcessorCellContext> m_contexts; std::unordered_map<key_type, db::LocalProcessorCellContext> m_contexts;
}; };
class DB_PLUGIN_PUBLIC LocalProcessorContexts class DB_PLUGIN_PUBLIC LocalProcessorContexts
{ {
public: public:
typedef std::map<db::Cell *, LocalProcessorCellContexts> contexts_per_cell_type; typedef std::unordered_map<db::Cell *, LocalProcessorCellContexts> contexts_per_cell_type;
typedef contexts_per_cell_type::iterator iterator; typedef contexts_per_cell_type::iterator iterator;
LocalProcessorContexts () LocalProcessorContexts ()
@ -229,7 +275,7 @@ class DB_PLUGIN_PUBLIC LocalProcessorContextComputationTask
: public tl::Task : public tl::Task
{ {
public: public:
LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist); LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders, db::Coord dist);
void perform (); void perform ();
private: private:
@ -240,7 +286,7 @@ private:
db::Cell *mp_subject_cell; db::Cell *mp_subject_cell;
db::ICplxTrans m_subject_cell_inst; db::ICplxTrans m_subject_cell_inst;
const db::Cell *mp_intruder_cell; const db::Cell *mp_intruder_cell;
std::pair<std::set<CellInstArray>, std::set<PolygonRef> > m_intruders; std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > m_intruders;
db::Coord m_dist; db::Coord m_dist;
}; };
@ -324,11 +370,11 @@ private:
mutable std::auto_ptr<tl::Job<LocalProcessorContextComputationWorker> > mp_cc_job; mutable std::auto_ptr<tl::Job<LocalProcessorContextComputationWorker> > mp_cc_job;
std::string description (const LocalOperation *op) const; std::string description (const LocalOperation *op) const;
void compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist) const; void compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders, db::Coord dist) const;
void do_compute_contexts (db::LocalProcessorCellContext *cell_context, const db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist) const; void do_compute_contexts (db::LocalProcessorCellContext *cell_context, const db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders, db::Coord dist) const;
void issue_compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist) const; void issue_compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair<std::unordered_set<CellInstArray>, std::unordered_set<PolygonRef> > &intruders, db::Coord dist) const;
void push_results (db::Cell *cell, unsigned int output_layer, const std::set<db::PolygonRef> &result) const; void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<db::PolygonRef> &result) const;
void compute_local_cell (const db::LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const LocalOperation *op, const std::pair<std::set<CellInstArray>, std::set<db::PolygonRef> > &intruders, std::set<db::PolygonRef> &result) const; void compute_local_cell (const db::LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const LocalOperation *op, const std::pair<std::unordered_set<CellInstArray>, std::unordered_set<db::PolygonRef> > &intruders, std::unordered_set<db::PolygonRef> &result) const;
}; };
} }

View File

@ -47,7 +47,7 @@ public:
/** /**
* @brief Constructor specifying an external vector for storing the polygons * @brief Constructor specifying an external vector for storing the polygons
*/ */
PolygonRefGenerator (db::Layout *layout, std::set<db::PolygonRef> &polyrefs) PolygonRefGenerator (db::Layout *layout, std::unordered_set<db::PolygonRef> &polyrefs)
: PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs) : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs)
{ } { }
@ -62,7 +62,7 @@ public:
private: private:
db::Layout *mp_layout; db::Layout *mp_layout;
std::set<db::PolygonRef> *mp_polyrefs; std::unordered_set<db::PolygonRef> *mp_polyrefs;
}; };
} }
@ -88,7 +88,7 @@ BoolAndOrNotLocalOperation::description () const
} }
void void
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const
{ {
db::EdgeProcessor ep; db::EdgeProcessor ep;
@ -147,7 +147,7 @@ SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wra
// .. nothing yet .. // .. nothing yet ..
} }
void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const
{ {
if (m_wrap_count == 0) { if (m_wrap_count == 0) {
return; return;

View File

@ -28,8 +28,8 @@
#include "dbLayout.h" #include "dbLayout.h"
#include "dbPluginCommon.h" #include "dbPluginCommon.h"
#include <map> #include <unordered_map>
#include <set> #include <unordered_set>
#include <vector> #include <vector>
namespace db namespace db
@ -87,7 +87,7 @@ public:
* @param interactions The interaction set * @param interactions The interaction set
* @param result The container to which the results are written * @param result The container to which the results are written
*/ */
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const = 0; virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const = 0;
/** /**
* @brief Indicates the desired behaviour when a shape does not have an intruder * @brief Indicates the desired behaviour when a shape does not have an intruder
@ -115,7 +115,7 @@ class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation
public: public:
BoolAndOrNotLocalOperation (bool is_and); BoolAndOrNotLocalOperation (bool is_and);
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const; virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const;
virtual on_empty_intruder_mode on_empty_intruder_hint () const; virtual on_empty_intruder_mode on_empty_intruder_hint () const;
virtual std::string description () const; virtual std::string description () const;
@ -134,7 +134,7 @@ class DB_PLUGIN_PUBLIC SelfOverlapMergeLocalOperation
public: public:
SelfOverlapMergeLocalOperation (unsigned int wrap_count); SelfOverlapMergeLocalOperation (unsigned int wrap_count);
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const; virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const;
virtual on_empty_intruder_mode on_empty_intruder_hint () const; virtual on_empty_intruder_mode on_empty_intruder_hint () const;
virtual std::string description () const; virtual std::string description () const;

View File

@ -55,7 +55,7 @@ public:
// .. nothing yet .. // .. nothing yet ..
} }
virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const
{ {
db::ShapeInteractions sized_interactions = interactions; db::ShapeInteractions sized_interactions = interactions;
for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
@ -91,7 +91,7 @@ public:
// .. nothing yet .. // .. nothing yet ..
} }
virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const
{ {
db::ShapeInteractions sized_interactions = interactions; db::ShapeInteractions sized_interactions = interactions;
for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {