diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index a10c0a99c..461d3e01f 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -463,7 +463,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const db::BoolAndOrNotLocalOperation op (and_op); - db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ()); proc.set_base_verbosity (base_verbosity ()); proc.set_threads (m_deep_layer.store ()->threads ()); proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ()); diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 92a2b1ed6..cddcebd6c 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -65,7 +65,7 @@ namespace db // --------------------------------------------------------------------------------------------- // Shape reference translator -template class shape_reference_translator; +template class shape_reference_translator; template class shape_reference_translator_with_trans; template @@ -228,44 +228,44 @@ private: // --------------------------------------------------------------------------------------------- // LocalProcessorCellContext implementation -template -local_processor_cell_context::local_processor_cell_context () +template +local_processor_cell_context::local_processor_cell_context () { // .. nothing yet .. } -template -local_processor_cell_context::local_processor_cell_context (const local_processor_cell_context &other) +template +local_processor_cell_context::local_processor_cell_context (const local_processor_cell_context &other) : m_propagated (other.m_propagated), m_drops (other.m_drops) { // .. nothing yet .. } -template +template void -local_processor_cell_context::add (db::local_processor_cell_context *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst) +local_processor_cell_context::add (db::local_processor_cell_context *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst) { - m_drops.push_back (local_processor_cell_drop (parent_context, parent, cell_inst)); + m_drops.push_back (local_processor_cell_drop (parent_context, parent, cell_inst)); } -template +template void -local_processor_cell_context::propagate (const std::unordered_set &res) +local_processor_cell_context::propagate (const std::unordered_set &res) { if (res.empty ()) { return; } - for (typename std::vector >::const_iterator d = m_drops.begin (); d != m_drops.end (); ++d) { + for (typename std::vector >::const_iterator d = m_drops.begin (); d != m_drops.end (); ++d) { tl_assert (d->parent_context != 0); tl_assert (d->parent != 0); db::Layout *subject_layout = d->parent->layout (); - shape_reference_translator_with_trans rt (subject_layout, d->cell_inst); - std::vector new_refs; + shape_reference_translator_with_trans rt (subject_layout, d->cell_inst); + std::vector new_refs; new_refs.reserve (res.size ()); - for (typename std::unordered_set::const_iterator r = res.begin (); r != res.end (); ++r) { + for (typename std::unordered_set::const_iterator r = res.begin (); r != res.end (); ++r) { new_refs.push_back (rt (*r)); } @@ -277,43 +277,46 @@ local_processor_cell_context::propagate (const std::unordered_set &res) } } -template class DB_PUBLIC local_processor_cell_context; -template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; // --------------------------------------------------------------------------------------------- // LocalProcessorCellContexts implementation -template -local_processor_cell_contexts::local_processor_cell_contexts () +template +local_processor_cell_contexts::local_processor_cell_contexts () : mp_intruder_cell (0) { // .. nothing yet .. } -template -local_processor_cell_contexts::local_processor_cell_contexts (const db::Cell *intruder_cell) +template +local_processor_cell_contexts::local_processor_cell_contexts (const db::Cell *intruder_cell) : mp_intruder_cell (intruder_cell) { // .. nothing yet .. } -template -db::local_processor_cell_context * -local_processor_cell_contexts::find_context (const context_key_type &intruders) +template +db::local_processor_cell_context * +local_processor_cell_contexts::find_context (const context_key_type &intruders) { - typename std::unordered_map >::iterator c = m_contexts.find (intruders); + typename std::unordered_map >::iterator c = m_contexts.find (intruders); return c != m_contexts.end () ? &c->second : 0; } -template -db::local_processor_cell_context * -local_processor_cell_contexts::create (const context_key_type &intruders) +template +db::local_processor_cell_context * +local_processor_cell_contexts::create (const context_key_type &intruders) { return &m_contexts[intruders]; } +template static void -subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout *layout, const db::local_processor *proc) +subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout *layout, const db::local_processor *proc) { if (other.empty ()) { return; @@ -351,8 +354,9 @@ subtract (std::unordered_set &res, const std::unordered_set static void -subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout * /*layout*/, const db::local_processor * /*proc*/) +subtract (std::unordered_set &res, const std::unordered_set &other, db::Layout * /*layout*/, const db::local_processor * /*proc*/) { // for edges, we don't use a boolean core but just set intersection for (std::unordered_set::const_iterator o = other.begin (); o != other.end (); ++o) { @@ -362,10 +366,10 @@ subtract (std::unordered_set &res, const std::unordered_set namespace { -template +template struct context_sorter { - bool operator () (const std::pair::context_key_type *, db::local_processor_cell_context *> &a, const std::pair::context_key_type *, db::local_processor_cell_context *> &b) + bool operator () (const std::pair::context_key_type *, db::local_processor_cell_context *> &a, const std::pair::context_key_type *, db::local_processor_cell_context *> &b) { return *a.first < *b.first; } @@ -373,14 +377,14 @@ struct context_sorter } -template +template void -local_processor_cell_contexts::compute_results (const local_processor_contexts &contexts, db::Cell *cell, const local_operation *op, unsigned int output_layer, const local_processor *proc) +local_processor_cell_contexts::compute_results (const local_processor_contexts &contexts, db::Cell *cell, const local_operation *op, unsigned int output_layer, const local_processor *proc) { CRONOLOGY_COMPUTE_BRACKET(event_compute_results) bool first = true; - std::unordered_set common; + std::unordered_set common; int index = 0; int total = int (m_contexts.size ()); @@ -388,15 +392,15 @@ local_processor_cell_contexts::compute_results (const local_processor_context // NOTE: we use the ordering provided by key_type::operator< rather than the unordered map to achieve // reproducability across different platforms. unordered_map is faster, but for processing them, // strict ordering is a more robust choice. - std::vector *> > sorted_contexts; + std::vector *> > sorted_contexts; sorted_contexts.reserve (m_contexts.size ()); - for (typename std::unordered_map >::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { + for (typename std::unordered_map >::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { sorted_contexts.push_back (std::make_pair (&c->first, &c->second)); } - std::sort (sorted_contexts.begin (), sorted_contexts.end (), context_sorter ()); + std::sort (sorted_contexts.begin (), sorted_contexts.end (), context_sorter ()); - for (typename std::vector *> >::const_iterator c = sorted_contexts.begin (); c != sorted_contexts.end (); ++c) { + for (typename std::vector *> >::const_iterator c = sorted_contexts.begin (); c != sorted_contexts.end (); ++c) { ++index; @@ -417,7 +421,7 @@ local_processor_cell_contexts::compute_results (const local_processor_context } else { - std::unordered_set res; + std::unordered_set res; { tl::MutexLocker locker (&c->second->lock ()); res = c->second->propagated (); @@ -437,8 +441,8 @@ local_processor_cell_contexts::compute_results (const local_processor_context CRONOLOGY_COMPUTE_BRACKET(event_propagate) - std::unordered_set lost; - for (typename std::unordered_set::const_iterator i = common.begin (); i != common.end (); ++i) { + std::unordered_set lost; + for (typename std::unordered_set::const_iterator i = common.begin (); i != common.end (); ++i) { if (res.find (*i) == res.end ()) { lost.insert (*i); } @@ -450,15 +454,15 @@ local_processor_cell_contexts::compute_results (const local_processor_context if (! lost.empty ()) { subtract (common, lost, cell->layout (), proc); - for (typename std::vector *> >::const_iterator cc = sorted_contexts.begin (); cc != c; ++cc) { + for (typename std::vector *> >::const_iterator cc = sorted_contexts.begin (); cc != c; ++cc) { cc->second->propagate (lost); } } } - std::unordered_set gained; - for (typename std::unordered_set::const_iterator i = res.begin (); i != res.end (); ++i) { + std::unordered_set gained; + for (typename std::unordered_set::const_iterator i = res.begin (); i != res.end (); ++i) { if (common.find (*i) == common.end ()) { gained.insert (*i); } @@ -483,50 +487,66 @@ local_processor_cell_contexts::compute_results (const local_processor_context proc->push_results (cell, output_layer, common); } -template class DB_PUBLIC local_processor_cell_contexts; -template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; // --------------------------------------------------------------------------------------------- -template -shape_interactions::shape_interactions () +template +shape_interactions::shape_interactions () : m_id (0) { // .. nothing yet .. } -template +template bool -shape_interactions::has_shape_id (unsigned int id) const +shape_interactions::has_intruder_shape_id (unsigned int id) const { - return m_shapes.find (id) != m_shapes.end (); + return m_intruder_shapes.find (id) != m_intruder_shapes.end (); } -template -void -shape_interactions::add_shape (unsigned int id, const T &shape) +template +bool +shape_interactions::has_subject_shape_id (unsigned int id) const { - m_shapes [id] = shape; + return m_subject_shapes.find (id) != m_subject_shapes.end (); } -template +template void -shape_interactions::add_subject (unsigned int id, const T &shape) +shape_interactions::add_intruder_shape (unsigned int id, const TI &shape) { - add_shape (id, shape); + m_intruder_shapes [id] = shape; +} + +template +void +shape_interactions::add_subject_shape (unsigned int id, const TS &shape) +{ + m_subject_shapes [id] = shape; +} + +template +void +shape_interactions::add_subject (unsigned int id, const TS &shape) +{ + m_subject_shapes [id] = shape; m_interactions.insert (std::make_pair (id, container::value_type::second_type ())); } -template +template void -shape_interactions::add_interaction (unsigned int subject_id, unsigned int intruder_id) +shape_interactions::add_interaction (unsigned int subject_id, unsigned int intruder_id) { m_interactions [subject_id].push_back (intruder_id); } -template +template const std::vector & -shape_interactions::intruders_for (unsigned int subject_id) const +shape_interactions::intruders_for (unsigned int subject_id) const { iterator i = m_interactions.find (subject_id); if (i == m_interactions.end ()) { @@ -537,21 +557,36 @@ shape_interactions::intruders_for (unsigned int subject_id) const } } -template -const T & -shape_interactions::shape (unsigned int id) const +template +const TS & +shape_interactions::subject_shape (unsigned int id) const { - typename std::unordered_map::const_iterator i = m_shapes.find (id); - if (i == m_shapes.end ()) { - static T s; + typename std::unordered_map::const_iterator i = m_subject_shapes.find (id); + if (i == m_subject_shapes.end ()) { + static TS s; return s; } else { return i->second; } } -template class DB_PUBLIC shape_interactions; -template class DB_PUBLIC shape_interactions; +template +const TI & +shape_interactions::intruder_shape (unsigned int id) const +{ + typename std::unordered_map::const_iterator i = m_intruder_shapes.find (id); + if (i == m_intruder_shapes.end ()) { + static TI s; + return s; + } else { + return i->second; + } +} + +template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; // --------------------------------------------------------------------------------------------- // Helper classes for the LocalProcessor @@ -573,46 +608,68 @@ inline unsigned int shape_flags () return db::ShapeIterator::Edges; } -template +template struct interaction_registration_shape2shape - : db::box_scanner_receiver2 + : db::box_scanner_receiver2 { public: - interaction_registration_shape2shape (db::Layout *layout, shape_interactions *result) + interaction_registration_shape2shape (db::Layout *layout, shape_interactions *result) : mp_result (result), mp_layout (layout) { // nothing yet .. } - void add (const T *ref1, unsigned int id1, const T *ref2, unsigned int id2) + void add (const TS *ref1, unsigned int id1, const TI *ref2, unsigned int id2) { - mp_result->add_shape (id1, *ref1); + mp_result->add_subject_shape (id1, *ref1); if (mp_layout) { // In order to guarantee the refs come from the subject layout, we'd need to // rewrite them - if (!mp_result->has_shape_id (id2)) { - db::shape_reference_translator rt (mp_layout); - mp_result->add_shape (id2, rt (*ref2)); + if (!mp_result->has_intruder_shape_id (id2)) { + db::shape_reference_translator rt (mp_layout); + mp_result->add_intruder_shape (id2, rt (*ref2)); } } else { - mp_result->add_shape (id2, *ref2); + mp_result->add_intruder_shape (id2, *ref2); } mp_result->add_interaction (id1, id2); } private: - shape_interactions *mp_result; + shape_interactions *mp_result; db::Layout *mp_layout; }; -template +template struct interaction_registration_shape1 + : db::box_scanner_receiver2 +{ +public: + interaction_registration_shape1 (shape_interactions *result) + : mp_result (result) + { + // nothing yet .. + } + + void add (const TS *ref1, unsigned int id1, const TI *ref2, unsigned int id2) + { + mp_result->add_subject_shape (id1, *ref1); + mp_result->add_intruder_shape (id2, *ref2); + mp_result->add_interaction (id1, id2); + } + +private: + shape_interactions *mp_result; +}; + +template +struct interaction_registration_shape1 : db::box_scanner_receiver { public: - interaction_registration_shape1 (shape_interactions *result) + interaction_registration_shape1 (shape_interactions *result) : mp_result (result) { // nothing yet .. @@ -620,35 +677,35 @@ public: void add (const T *ref1, unsigned int id1, const T *ref2, unsigned int id2) { - mp_result->add_shape (id1, *ref1); - mp_result->add_shape (id2, *ref2); + mp_result->add_subject_shape (id1, *ref1); + mp_result->add_intruder_shape (id2, *ref2); mp_result->add_interaction (id1, id2); } private: - shape_interactions *mp_result; + shape_interactions *mp_result; }; -template +template struct interaction_registration_shape2inst - : db::box_scanner_receiver2 + : db::box_scanner_receiver2 { public: - interaction_registration_shape2inst (db::Layout *subject_layout, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, shape_interactions *result) + interaction_registration_shape2inst (db::Layout *subject_layout, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, shape_interactions *result) : mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result) { // nothing yet .. } - void add (const T *ref, unsigned int id1, const db::CellInstArray *inst, unsigned int inst_id) + void add (const TS *ref, unsigned int id1, const db::CellInstArray *inst, unsigned int inst_id) { const db::Cell &intruder_cell = mp_intruder_layout->cell (inst->object ().cell_index ()); db::box_convert inst_bc (*mp_intruder_layout, m_intruder_layer); - mp_result->add_shape (id1, *ref); + mp_result->add_subject_shape (id1, *ref); // Find all instance array members that potentially interact with the shape and use // add_shapes_from_intruder_inst on them - db::Box ref_box = db::box_convert () (*ref); + db::Box ref_box = db::box_convert () (*ref); for (db::CellInstArray::iterator n = inst->begin_touching (ref_box.enlarged (db::Vector (m_dist - 1, m_dist - 1)), inst_bc); !n.at_end (); ++n) { db::ICplxTrans tn = inst->complex_trans (*n); db::Box region = ref_box.transformed (tn.inverted ()).enlarged (db::Vector (m_dist, m_dist)) & intruder_cell.bbox (m_intruder_layer).enlarged (db::Vector (m_dist, m_dist)); @@ -663,31 +720,31 @@ private: const db::Layout *mp_intruder_layout; unsigned int m_intruder_layer; db::Coord m_dist; - shape_interactions *mp_result; - std::unordered_map m_inst_shape_ids; + shape_interactions *mp_result; + std::unordered_map 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 ®ion) { - db::shape_reference_translator rt (mp_subject_layout); + db::shape_reference_translator rt (mp_subject_layout); // Look up all shapes from the intruder instance which interact with the subject shape // (given through region) // TODO: should be lighter, cache, handle arrays .. db::RecursiveShapeIterator si (*mp_intruder_layout, intruder_cell, m_intruder_layer, region); - si.shape_flags (shape_flags ()); + si.shape_flags (shape_flags ()); while (! si.at_end ()) { // NOTE: we intentionally rewrite to the *subject* layout - this way polygon refs in the context come from the // subject, not from the intruder. - T ref2 = rt (*si.shape ().basic_ptr (typename T::tag ()), tn * si.trans ()); + TI ref2 = rt (*si.shape ().basic_ptr (typename TI::tag ()), tn * si.trans ()); // reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on // the intruder side. - typename std::unordered_map::const_iterator k = m_inst_shape_ids.find (ref2); + typename std::unordered_map::const_iterator k = m_inst_shape_ids.find (ref2); if (k == m_inst_shape_ids.end ()) { k = m_inst_shape_ids.insert (std::make_pair (ref2, mp_result->next_id ())).first; - mp_result->add_shape (k->second, ref2); + mp_result->add_intruder_shape (k->second, ref2); } @@ -865,8 +922,8 @@ private: // --------------------------------------------------------------------------------------------- // LocalProcessorContextComputationTask implementation -template -local_processor_context_computation_task::local_processor_context_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) +template +local_processor_context_computation_task::local_processor_context_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) : tl::Task (), 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), @@ -876,29 +933,31 @@ local_processor_context_computation_task::local_processor_context_computation m_intruders.swap (intruders); } -template +template void -local_processor_context_computation_task::perform () +local_processor_context_computation_task::perform () { mp_proc->compute_contexts (*mp_contexts, mp_parent_context, mp_subject_parent, mp_subject_cell, m_subject_cell_inst, mp_intruder_cell, m_intruders, m_dist); } -template class DB_PUBLIC local_processor_context_computation_task; -template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; // --------------------------------------------------------------------------------------------- // LocalProcessorResultComputationTask implementation -template -local_processor_result_computation_task::local_processor_result_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::Cell *cell, local_processor_cell_contexts *cell_contexts, const local_operation *op, unsigned int output_layer) +template +local_processor_result_computation_task::local_processor_result_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::Cell *cell, local_processor_cell_contexts *cell_contexts, const local_operation *op, unsigned int output_layer) : mp_proc (proc), mp_contexts (&contexts), mp_cell (cell), mp_cell_contexts (cell_contexts), mp_op (op), m_output_layer (output_layer) { // .. nothing yet .. } -template +template void -local_processor_result_computation_task::perform () +local_processor_result_computation_task::perform () { mp_cell_contexts->compute_results (*mp_contexts, mp_cell, mp_op, m_output_layer, mp_proc); @@ -907,13 +966,13 @@ local_processor_result_computation_task::perform () tl::MutexLocker locker (& mp_contexts->lock ()); #if defined(ENABLE_DB_HP_SANITY_ASSERTIONS) - std::set *> td; - for (typename db::local_processor_cell_contexts::iterator i = mp_cell_contexts->begin (); i != mp_cell_contexts->end (); ++i) { + std::set *> td; + for (typename db::local_processor_cell_contexts::iterator i = mp_cell_contexts->begin (); i != mp_cell_contexts->end (); ++i) { td.insert (&i->second); } - for (typename db::local_processor_cell_contexts::contexts_per_cell_type::iterator pcc = mp_contexts->context_map ().begin (); pcc != mp_contexts->context_map ().end (); ++pcc) { - for (typename db::local_processor_cell_contexts::iterator i = pcc->second.begin (); i != pcc->second.end (); ++i) { - for (typename db::local_processor_cell_context::drop_iterator j = i->second.begin_drops (); j != i->second.end_drops (); ++j) { + for (typename db::local_processor_cell_contexts::contexts_per_cell_type::iterator pcc = mp_contexts->context_map ().begin (); pcc != mp_contexts->context_map ().end (); ++pcc) { + for (typename db::local_processor_cell_contexts::iterator i = pcc->second.begin (); i != pcc->second.end (); ++i) { + for (typename db::local_processor_cell_context::drop_iterator j = i->second.begin_drops (); j != i->second.end_drops (); ++j) { if (td.find (j->parent_context) != td.end ()) { tl_assert (false); } @@ -926,28 +985,30 @@ local_processor_result_computation_task::perform () } } -template class DB_PUBLIC local_processor_result_computation_task; -template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; // --------------------------------------------------------------------------------------------- // LocalProcessor implementation -template -local_processor::local_processor (db::Layout *layout, db::Cell *top) +template +local_processor::local_processor (db::Layout *layout, db::Cell *top) : mp_subject_layout (layout), mp_intruder_layout (layout), mp_subject_top (top), mp_intruder_top (top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30) { // .. nothing yet .. } -template -local_processor::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top) +template +local_processor::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top) : mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), mp_subject_top (subject_top), mp_intruder_top (intruder_top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30) { // .. nothing yet .. } -template -std::string local_processor::description (const local_operation *op) const +template +std::string local_processor::description (const local_operation *op) const { if (op && m_description.empty ()) { return op->description (); @@ -956,18 +1017,18 @@ std::string local_processor::description (const local_operation *op) const } } -template -void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer) +template +void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer) { tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Executing ")) + description (op)); - local_processor_contexts contexts; + local_processor_contexts contexts; compute_contexts (contexts, op, subject_layer, intruder_layer); compute_results (contexts, op, output_layer); } -template -void local_processor::push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const +template +void local_processor::push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const { if (! result.empty ()) { tl::MutexLocker locker (&cell->layout ()->lock ()); @@ -975,15 +1036,15 @@ void local_processor::push_results (db::Cell *cell, unsigned int output_layer } } -template -void local_processor::compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, unsigned int intruder_layer) const +template +void local_processor::compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, unsigned int intruder_layer) const { try { tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 10, tl::to_string (tr ("Computing contexts for ")) + description (op)); if (m_nthreads > 0) { - mp_cc_job.reset (new tl::Job > (m_nthreads)); + mp_cc_job.reset (new tl::Job > (m_nthreads)); } else { mp_cc_job.reset (0); } @@ -992,7 +1053,7 @@ void local_processor::compute_contexts (local_processor_contexts &contexts contexts.set_intruder_layer (intruder_layer); contexts.set_subject_layer (subject_layer); - typename local_processor_cell_contexts::context_key_type intruders; + typename local_processor_cell_contexts::context_key_type intruders; issue_compute_contexts (contexts, 0, 0, mp_subject_top, db::ICplxTrans (), mp_intruder_top, intruders, op->dist ()); if (mp_cc_job.get ()) { @@ -1006,33 +1067,33 @@ void local_processor::compute_contexts (local_processor_contexts &contexts } } -template -void local_processor::issue_compute_contexts (local_processor_contexts &contexts, - db::local_processor_cell_context *parent_context, +template +void local_processor::issue_compute_contexts (local_processor_contexts &contexts, + db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, - typename local_processor_cell_contexts::context_key_type &intruders, + typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const { bool is_small_job = subject_cell->begin ().at_end (); if (! is_small_job && mp_cc_job.get ()) { - mp_cc_job->schedule (new local_processor_context_computation_task (this, contexts, parent_context, subject_parent, subject_cell, subject_cell_inst, intruder_cell, intruders, dist)); + mp_cc_job->schedule (new local_processor_context_computation_task (this, contexts, parent_context, subject_parent, subject_cell, subject_cell_inst, intruder_cell, intruders, dist)); } else { compute_contexts (contexts, parent_context, subject_parent, subject_cell, subject_cell_inst, intruder_cell, intruders, dist); } } -template -void local_processor::compute_contexts (local_processor_contexts &contexts, - db::local_processor_cell_context *parent_context, +template +void local_processor::compute_contexts (local_processor_contexts &contexts, + db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, - const typename local_processor_cell_contexts::context_key_type &intruders, + const typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const { CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts) @@ -1045,7 +1106,7 @@ void local_processor::compute_contexts (local_processor_contexts &contexts } } - db::local_processor_cell_context *cell_context = 0; + db::local_processor_cell_context *cell_context = 0; // prepare a new cell context: this has to happen in a thread-safe way as we share the contexts // object between threads @@ -1053,17 +1114,17 @@ void local_processor::compute_contexts (local_processor_contexts &contexts { tl::MutexLocker locker (& contexts.lock ()); - db::local_processor_cell_contexts &cell_contexts = contexts.contexts_per_cell (subject_cell, intruder_cell); + db::local_processor_cell_contexts &cell_contexts = contexts.contexts_per_cell (subject_cell, intruder_cell); #if defined(ENABLE_DB_HP_SANITY_ASSERTIONS) if (subject_parent) { - typename db::local_processor_cell_contexts::contexts_per_cell_type::iterator pcc = contexts.context_map ().find (subject_parent); + typename db::local_processor_cell_contexts::contexts_per_cell_type::iterator pcc = contexts.context_map ().find (subject_parent); if (pcc == contexts.context_map ().end ()) { tl_assert (false); } tl_assert (pcc->first == subject_parent); bool any = false; - for (typename db::local_processor_cell_contexts::iterator pcci = pcc->second.begin (); pcci != pcc->second.end () && !any; ++pcci) { + for (typename db::local_processor_cell_contexts::iterator pcci = pcc->second.begin (); pcci != pcc->second.end () && !any; ++pcci) { any = (&pcci->second == parent_context); } if (!any) { @@ -1100,7 +1161,7 @@ void local_processor::compute_contexts (local_processor_contexts &contexts if (! subject_cell->begin ().at_end ()) { - typedef std::pair, std::unordered_set > interaction_value_type; + typedef std::pair, std::unordered_set > interaction_value_type; std::unordered_map interactions; @@ -1116,7 +1177,7 @@ void local_processor::compute_contexts (local_processor_contexts &contexts // TODO: can we shortcut this if interactions is empty? { db::box_scanner2 scanner; - interaction_registration_inst2inst rec (mp_subject_layout, contexts.subject_layer (), mp_intruder_layout, contexts.intruder_layer (), dist, &interactions); + interaction_registration_inst2inst rec (mp_subject_layout, contexts.subject_layer (), mp_intruder_layout, contexts.intruder_layer (), dist, &interactions); unsigned int id = 0; @@ -1164,8 +1225,8 @@ void local_processor::compute_contexts (local_processor_contexts &contexts // TODO: can we shortcut this if interactions is empty? { - db::box_scanner2 scanner; - interaction_registration_inst2shape rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions); + db::box_scanner2 scanner; + interaction_registration_inst2shape rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions); for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) { if (! inst_bcs (i->cell_inst ()).empty ()) { @@ -1173,17 +1234,17 @@ void local_processor::compute_contexts (local_processor_contexts &contexts } } - for (typename std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (typename std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert2 (i.operator-> (), 0); } if (intruder_shapes) { - for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags ()); !i.at_end (); ++i) { - scanner.insert2 (i->basic_ptr (typename T::tag ()), 0); + for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + scanner.insert2 (i->basic_ptr (typename TI::tag ()), 0); } } - scanner.process (rec, dist, inst_bcs, db::box_convert ()); + scanner.process (rec, dist, inst_bcs, db::box_convert ()); } for (typename std::unordered_map::const_iterator i = interactions.begin (); i != interactions.end (); ++i) { @@ -1198,12 +1259,12 @@ void local_processor::compute_contexts (local_processor_contexts &contexts if (! nbox.empty ()) { - typename local_processor_cell_contexts::context_key_type intruders_below; + typename local_processor_cell_contexts::context_key_type intruders_below; - db::shape_reference_translator_with_trans rt (mp_subject_layout, tni); + db::shape_reference_translator_with_trans rt (mp_subject_layout, tni); - for (typename std::unordered_set::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) { - if (nbox.overlaps (db::box_convert () (*p))) { + for (typename std::unordered_set::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) { + if (nbox.overlaps (db::box_convert () (*p))) { intruders_below.second.insert (rt (*p)); } } @@ -1232,9 +1293,9 @@ void local_processor::compute_contexts (local_processor_contexts &contexts } } -template +template void -local_processor::compute_results (local_processor_contexts &contexts, const local_operation *op, unsigned int output_layer) const +local_processor::compute_results (local_processor_contexts &contexts, const local_operation *op, unsigned int output_layer) const { tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 10, tl::to_string (tr ("Computing results for ")) + description (op)); @@ -1244,7 +1305,7 @@ local_processor::compute_results (local_processor_contexts &contexts, cons if (m_nthreads > 0) { - std::auto_ptr > > rc_job (new tl::Job > (m_nthreads)); + std::auto_ptr > > rc_job (new tl::Job > (m_nthreads)); // schedule computation jobs in "waves": we need to make sure they are executed // bottom-up. So we identify a new bunch of cells each time we pass through the cell set @@ -1270,12 +1331,12 @@ local_processor::compute_results (local_processor_contexts &contexts, cons for (std::vector::const_iterator bu = cells_bu.begin (); bu != cells_bu.end (); ++bu) { - typename local_processor_contexts::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu)); + typename local_processor_contexts::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu)); if (cpc != contexts.context_map ().end ()) { if (later.find (*bu) == later.end ()) { - rc_job->schedule (new local_processor_result_computation_task (this, contexts, cpc->first, &cpc->second, op, output_layer)); + rc_job->schedule (new local_processor_result_computation_task (this, contexts, cpc->first, &cpc->second, op, output_layer)); any = true; } else { @@ -1307,7 +1368,7 @@ local_processor::compute_results (local_processor_contexts &contexts, cons for (db::Layout::bottom_up_const_iterator bu = mp_subject_layout->begin_bottom_up (); bu != mp_subject_layout->end_bottom_up (); ++bu) { - typename local_processor_contexts::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu)); + typename local_processor_contexts::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu)); if (cpc != contexts.context_map ().end ()) { cpc->second.compute_results (contexts, cpc->first, op, output_layer, this); contexts.context_map ().erase (cpc); @@ -1318,9 +1379,88 @@ local_processor::compute_results (local_processor_contexts &contexts, cons } } +template +struct scan_shape2shape_same_layer +{ + void + operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set &intruders, shape_interactions &interactions, db::Coord dist) const + { + db::box_scanner2 scanner; + interaction_registration_shape1 rec (&interactions); + + unsigned int id = subject_id0; + for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + const TS *ref = i->basic_ptr (typename TS::tag ()); + scanner.insert1 (ref, id++); + } + + // TODO: can we confine this search to the subject's (sized) bounding box? + for (typename std::set::const_iterator i = intruders.begin (); i != intruders.end (); ++i) { + scanner.insert2 (i.operator-> (), interactions.next_id ()); + } + + scanner.process (rec, dist, db::box_convert (), db::box_convert ()); + } +}; + template +struct scan_shape2shape_same_layer +{ + void + operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set &intruders, shape_interactions &interactions, db::Coord dist) const + { + db::box_scanner scanner; + interaction_registration_shape1 rec (&interactions); + + unsigned int id = subject_id0; + for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + const T *ref = i->basic_ptr (typename T::tag ()); + scanner.insert (ref, id++); + } + + // TODO: can we confine this search to the subject's (sized) bounding box? + for (typename std::set::const_iterator i = intruders.begin (); i != intruders.end (); ++i) { + scanner.insert (i.operator-> (), interactions.next_id ()); + } + + scanner.process (rec, dist, db::box_convert ()); + } +}; + +template +struct scan_shape2shape_different_layers +{ + void + operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set &intruders, shape_interactions &interactions, db::Coord dist) + { + db::box_scanner2 scanner; + interaction_registration_shape2shape rec (layout, &interactions); + + unsigned int id = subject_id0; + for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + const TS *ref = i->basic_ptr (typename TS::tag ()); + scanner.insert1 (ref, id++); + } + + // TODO: can we confine this search to the subject's (sized) bounding box? + for (typename std::set::const_iterator i = intruders.begin (); i != intruders.end (); ++i) { + scanner.insert2 (i.operator-> (), interactions.next_id ()); + } + + if (intruder_shapes) { + // TODO: can we confine this search to the subject's (sized) bounding box? + for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + scanner.insert2 (i->basic_ptr (typename TI::tag ()), interactions.next_id ()); + } + } + + scanner.process (rec, dist, db::box_convert (), db::box_convert ()); + } +}; + +template void -local_processor::compute_local_cell (const db::local_processor_contexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation *op, const typename local_processor_cell_contexts::context_key_type &intruders, std::unordered_set &result) const +local_processor::compute_local_cell (const db::local_processor_contexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation *op, const typename local_processor_cell_contexts::context_key_type &intruders, std::unordered_set &result) const { const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ()); @@ -1334,21 +1474,21 @@ local_processor::compute_local_cell (const db::local_processor_contexts &c // local shapes vs. child cell - shape_interactions interactions; + shape_interactions interactions; db::box_convert inst_bci (*mp_intruder_layout, contexts.intruder_layer ()); // insert dummy interactions to accommodate subject vs. nothing and assign an ID // range for the subject shapes. unsigned int subject_id0 = 0; - for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { unsigned int id = interactions.next_id (); if (subject_id0 == 0) { subject_id0 = id; } - if (op->on_empty_intruder_hint () != local_operation::Drop) { - const T *ref = i->basic_ptr (typename T::tag ()); + if (op->on_empty_intruder_hint () != local_operation::Drop) { + const TS *ref = i->basic_ptr (typename TS::tag ()); interactions.add_subject (id, *ref); } @@ -1358,46 +1498,12 @@ local_processor::compute_local_cell (const db::local_processor_contexts &c if (subject_cell == intruder_cell && contexts.subject_layer () == contexts.intruder_layer ()) { - db::box_scanner scanner; - interaction_registration_shape1 rec (&interactions); - - unsigned int id = subject_id0; - for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { - const T *ref = i->basic_ptr (typename T::tag ()); - scanner.insert (ref, id++); - } - -// TODO: TODO: can we confine this search to the subject's (sized) bounding box? - for (typename std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { - scanner.insert (i.operator-> (), interactions.next_id ()); - } - - scanner.process (rec, op->dist (), db::box_convert ()); + scan_shape2shape_same_layer () (subject_shapes, subject_id0, intruders.second, interactions, op->dist ()); } else { - db::box_scanner2 scanner; - interaction_registration_shape2shape rec (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout, &interactions); - - unsigned int id = subject_id0; - for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { - const T *ref = i->basic_ptr (typename T::tag ()); - scanner.insert1 (ref, id++); - } - -// TODO: can we confine this search to the subject's (sized) bounding box? - for (typename std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { - scanner.insert2 (i.operator-> (), interactions.next_id ()); - } - - if (intruder_shapes) { -// TODO: can we confine this search to the subject's (sized) bounding box? - for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags ()); !i.at_end (); ++i) { - scanner.insert2 (i->basic_ptr (typename T::tag ()), interactions.next_id ()); - } - } - - scanner.process (rec, op->dist (), db::box_convert (), db::box_convert ()); + db::Layout *target_layout = (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout); + scan_shape2shape_different_layers () (target_layout, subject_shapes, intruder_shapes, subject_id0, intruders.second, interactions, op->dist ()); } @@ -1405,12 +1511,12 @@ local_processor::compute_local_cell (const db::local_processor_contexts &c if (! subject_shapes->empty () && ! ((! intruder_cell || intruder_cell->begin ().at_end ()) && intruders.first.empty ())) { - db::box_scanner2 scanner; - interaction_registration_shape2inst rec (mp_subject_layout, mp_intruder_layout, contexts.intruder_layer (), op->dist (), &interactions); + db::box_scanner2 scanner; + interaction_registration_shape2inst rec (mp_subject_layout, mp_intruder_layout, contexts.intruder_layer (), op->dist (), &interactions); unsigned int id = subject_id0; - for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { - scanner.insert1 (i->basic_ptr (typename T::tag ()), id++); + for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + scanner.insert1 (i->basic_ptr (typename TS::tag ()), id++); } unsigned int inst_id = 0; @@ -1437,15 +1543,17 @@ local_processor::compute_local_cell (const db::local_processor_contexts &c } } - scanner.process (rec, op->dist (), db::box_convert (), inst_bci); + scanner.process (rec, op->dist (), db::box_convert (), inst_bci); } op->compute_local (mp_subject_layout, interactions, result, m_max_vertex_count, m_area_ratio); } -template class DB_PUBLIC local_processor; -template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; } diff --git a/src/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index a823705b4..6665c3c96 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -42,12 +42,12 @@ namespace db { -template class local_processor; -template class local_processor_cell_context; -template class local_processor_contexts; +template class local_processor; +template class local_processor_cell_context; +template class local_processor_contexts; // TODO: move this somewhere else? -template +template class DB_PUBLIC shape_interactions { public: @@ -67,12 +67,15 @@ public: return m_interactions.end (); } - bool has_shape_id (unsigned int id) const; - void add_shape (unsigned int id, const T &shape); - void add_subject (unsigned int id, const T &shape); + bool has_intruder_shape_id (unsigned int id) const; + bool has_subject_shape_id (unsigned int id) const; + void add_intruder_shape (unsigned int id, const TI &shape); + void add_subject_shape (unsigned int id, const TS &shape); + void add_subject (unsigned int id, const TS &shape); void add_interaction (unsigned int subject_id, unsigned int intruder_id); const std::vector &intruders_for (unsigned int subject_id) const; - const T &shape (unsigned int id) const; + const TS &subject_shape (unsigned int id) const; + const TI &intruder_shape (unsigned int id) const; unsigned int next_id () { @@ -81,45 +84,46 @@ public: private: std::unordered_map > m_interactions; - std::unordered_map m_shapes; + std::unordered_map m_subject_shapes; + std::unordered_map m_intruder_shapes; unsigned int m_id; }; // TODO: should be hidden (private data?) -template +template struct DB_PUBLIC local_processor_cell_drop { - local_processor_cell_drop (db::local_processor_cell_context *_parent_context, db::Cell *_parent, const db::ICplxTrans &_cell_inst) + local_processor_cell_drop (db::local_processor_cell_context *_parent_context, db::Cell *_parent, const db::ICplxTrans &_cell_inst) : parent_context (_parent_context), parent (_parent), cell_inst (_cell_inst) { // .. nothing yet .. } - db::local_processor_cell_context *parent_context; + db::local_processor_cell_context *parent_context; db::Cell *parent; db::ICplxTrans cell_inst; }; // TODO: should be hidden (private data?) -template +template class DB_PUBLIC local_processor_cell_context { public: typedef std::pair parent_inst_type; - typedef typename std::vector >::const_iterator drop_iterator; + typedef typename std::vector >::const_iterator drop_iterator; local_processor_cell_context (); local_processor_cell_context (const local_processor_cell_context &other); - void add (db::local_processor_cell_context *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst); - void propagate (const std::unordered_set &res); + void add (db::local_processor_cell_context *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst); + void propagate (const std::unordered_set &res); - std::unordered_set &propagated () + std::unordered_set &propagated () { return m_propagated; } - const std::unordered_set &propagated () const + const std::unordered_set &propagated () const { return m_propagated; } @@ -147,25 +151,25 @@ public: } private: - std::unordered_set m_propagated; - std::vector > m_drops; + std::unordered_set m_propagated; + std::vector > m_drops; tl::Mutex m_lock; }; -template +template class DB_PUBLIC local_processor_cell_contexts { public: - typedef std::pair, std::set > context_key_type; - typedef std::unordered_map > context_map_type; + typedef std::pair, std::set > context_key_type; + typedef std::unordered_map > context_map_type; typedef typename context_map_type::const_iterator iterator; local_processor_cell_contexts (); local_processor_cell_contexts (const db::Cell *intruder_cell); - db::local_processor_cell_context *find_context (const context_key_type &intruders); - db::local_processor_cell_context *create (const context_key_type &intruders); - void compute_results (const local_processor_contexts &contexts, db::Cell *cell, const local_operation *op, unsigned int output_layer, const local_processor *proc); + db::local_processor_cell_context *find_context (const context_key_type &intruders); + db::local_processor_cell_context *create (const context_key_type &intruders); + void compute_results (const local_processor_contexts &contexts, db::Cell *cell, const local_operation *op, unsigned int output_layer, const local_processor *proc); iterator begin () const { @@ -179,14 +183,14 @@ public: private: const db::Cell *mp_intruder_cell; - std::unordered_map > m_contexts; + std::unordered_map > m_contexts; }; -template +template class DB_PUBLIC local_processor_contexts { public: - typedef std::unordered_map > contexts_per_cell_type; + typedef std::unordered_map > contexts_per_cell_type; typedef typename contexts_per_cell_type::iterator iterator; local_processor_contexts () @@ -206,11 +210,11 @@ public: m_contexts_per_cell.clear (); } - local_processor_cell_contexts &contexts_per_cell (db::Cell *subject_cell, const db::Cell *intruder_cell) + local_processor_cell_contexts &contexts_per_cell (db::Cell *subject_cell, const db::Cell *intruder_cell) { typename contexts_per_cell_type::iterator ctx = m_contexts_per_cell.find (subject_cell); if (ctx == m_contexts_per_cell.end ()) { - ctx = m_contexts_per_cell.insert (std::make_pair (subject_cell, local_processor_cell_contexts (intruder_cell))).first; + ctx = m_contexts_per_cell.insert (std::make_pair (subject_cell, local_processor_cell_contexts (intruder_cell))).first; } return ctx->second; } @@ -261,27 +265,27 @@ private: mutable tl::Mutex m_lock; }; -template +template class DB_PUBLIC local_processor_context_computation_task : public tl::Task { public: - local_processor_context_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist); + local_processor_context_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist); void perform (); private: - const local_processor *mp_proc; - local_processor_contexts *mp_contexts; - db::local_processor_cell_context *mp_parent_context; + const local_processor *mp_proc; + local_processor_contexts *mp_contexts; + db::local_processor_cell_context *mp_parent_context; db::Cell *mp_subject_parent; db::Cell *mp_subject_cell; db::ICplxTrans m_subject_cell_inst; const db::Cell *mp_intruder_cell; - typename local_processor_cell_contexts::context_key_type m_intruders; + typename local_processor_cell_contexts::context_key_type m_intruders; db::Coord m_dist; }; -template +template class DB_PUBLIC local_processor_context_computation_worker : public tl::Worker { @@ -294,28 +298,28 @@ public: void perform_task (tl::Task *task) { - static_cast *> (task)->perform (); + static_cast *> (task)->perform (); } }; -template +template class DB_PUBLIC local_processor_result_computation_task : public tl::Task { public: - local_processor_result_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::Cell *cell, local_processor_cell_contexts *cell_contexts, const local_operation *op, unsigned int output_layer); + local_processor_result_computation_task (const local_processor *proc, local_processor_contexts &contexts, db::Cell *cell, local_processor_cell_contexts *cell_contexts, const local_operation *op, unsigned int output_layer); void perform (); private: - const local_processor *mp_proc; - local_processor_contexts *mp_contexts; + const local_processor *mp_proc; + local_processor_contexts *mp_contexts; db::Cell *mp_cell; - local_processor_cell_contexts *mp_cell_contexts; - const local_operation *mp_op; + local_processor_cell_contexts *mp_cell_contexts; + const local_operation *mp_op; unsigned int m_output_layer; }; -template +template class DB_PUBLIC local_processor_result_computation_worker : public tl::Worker { @@ -328,19 +332,19 @@ public: void perform_task (tl::Task *task) { - static_cast *> (task)->perform (); + static_cast *> (task)->perform (); } }; -template +template class DB_PUBLIC local_processor { public: local_processor (db::Layout *layout, db::Cell *top); local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell); - void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer); - void compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, unsigned int intruder_layer) const; - void compute_results (local_processor_contexts &contexts, const local_operation *op, unsigned int output_layer) const; + void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer); + void compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, unsigned int intruder_layer) const; + void compute_results (local_processor_contexts &contexts, const local_operation *op, unsigned int output_layer) const; void set_description (const std::string &d) { @@ -388,8 +392,8 @@ public: } private: - template friend class local_processor_cell_contexts; - template friend class local_processor_context_computation_task; + template friend class local_processor_cell_contexts; + template friend class local_processor_context_computation_task; db::Layout *mp_subject_layout; const db::Layout *mp_intruder_layout; @@ -400,14 +404,14 @@ private: size_t m_max_vertex_count; double m_area_ratio; int m_base_verbosity; - mutable std::auto_ptr > > mp_cc_job; + mutable std::auto_ptr > > mp_cc_job; - std::string description (const local_operation *op) const; - void compute_contexts (db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; - void do_compute_contexts (db::local_processor_cell_context *cell_context, const db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; - void issue_compute_contexts (db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; - void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const; - void compute_local_cell (const db::local_processor_contexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation *op, const typename local_processor_cell_contexts::context_key_type &intruders, std::unordered_set &result) const; + std::string description (const local_operation *op) const; + void compute_contexts (db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; + void do_compute_contexts (db::local_processor_cell_context *cell_context, const db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; + void issue_compute_contexts (db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; + void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const; + void compute_local_cell (const db::local_processor_contexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation *op, const typename local_processor_cell_contexts::context_key_type &intruders, std::unordered_set &result) const; }; } @@ -415,8 +419,8 @@ private: namespace tl { -template -struct type_traits > : public tl::type_traits +template +struct type_traits > : public tl::type_traits { // mark "LocalProcessor" as not having a default ctor and no copy ctor typedef tl::false_tag has_default_constructor; diff --git a/src/db/db/dbLocalOperation.cc b/src/db/db/dbLocalOperation.cc index 3545ce3b3..0abc895aa 100644 --- a/src/db/db/dbLocalOperation.cc +++ b/src/db/db/dbLocalOperation.cc @@ -45,7 +45,7 @@ BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and) // .. nothing yet .. } -local_operation::on_empty_intruder_mode +local_operation::on_empty_intruder_mode BoolAndOrNotLocalOperation::on_empty_intruder_hint () const { return m_is_and ? local_operation::Drop : local_operation::Copy; @@ -58,22 +58,22 @@ BoolAndOrNotLocalOperation::description () const } void -BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const +BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const { db::EdgeProcessor ep; size_t p1 = 0, p2 = 1; std::set others; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - others.insert (interactions.shape (*j)); + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); } } - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::PolygonRef &subject = interactions.shape (i->first); + const db::PolygonRef &subject = interactions.subject_shape (i->first); if (others.find (subject) != others.end ()) { if (m_is_and) { result.insert (subject); @@ -119,7 +119,7 @@ SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wra // .. nothing yet .. } -void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const +void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const { if (m_wrap_count == 0) { return; @@ -130,23 +130,23 @@ void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const sh size_t p1 = 0, p2 = 1; std::set seen; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { if (seen.find (i->first) == seen.end ()) { seen.insert (i->first); - const db::PolygonRef &subject = interactions.shape (i->first); + const db::PolygonRef &subject = interactions.subject_shape (i->first); for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) { ep.insert (*e, p1); } p1 += 2; } - for (db::shape_interactions::iterator2 o = i->second.begin (); o != i->second.end (); ++o) { + for (db::shape_interactions::iterator2 o = i->second.begin (); o != i->second.end (); ++o) { // don't take the same (really the same, not an identical one) shape twice - the interaction // set does not take care to list just one copy of the same item on the intruder side. if (seen.find (*o) == seen.end ()) { seen.insert (*o); - const db::PolygonRef &intruder = interactions.shape (*o); + const db::PolygonRef &intruder = interactions.intruder_shape (*o); for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) { ep.insert (*e, p2); } diff --git a/src/db/db/dbLocalOperation.h b/src/db/db/dbLocalOperation.h index b0bba3458..a818678fe 100644 --- a/src/db/db/dbLocalOperation.h +++ b/src/db/db/dbLocalOperation.h @@ -36,7 +36,7 @@ namespace db { -template class shape_interactions; +template class shape_interactions; /** * @brief A base class for "local operations" @@ -49,7 +49,7 @@ template class shape_interactions; * This class implements the actual operation. It receives a * cluster of subject shapes vs. corresponding intruder shapes. */ -template +template class DB_PUBLIC local_operation { public: @@ -89,7 +89,7 @@ public: * @param interactions The interaction set * @param result The container to which the results are written */ - virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const = 0; + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const = 0; /** * @brief Indicates the desired behaviour when a shape does not have an intruder @@ -112,12 +112,12 @@ public: * @brief Implements a boolean AND or NOT operation */ class DB_PUBLIC BoolAndOrNotLocalOperation - : public local_operation + : public local_operation { public: BoolAndOrNotLocalOperation (bool is_and); - virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const; + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const; virtual on_empty_intruder_mode on_empty_intruder_hint () const; virtual std::string description () const; @@ -131,12 +131,12 @@ private: * the original shapes overlap at least "wrap_count" times. */ class DB_PUBLIC SelfOverlapMergeLocalOperation - : public local_operation + : public local_operation { public: SelfOverlapMergeLocalOperation (unsigned int wrap_count); - virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const; + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const; virtual on_empty_intruder_mode on_empty_intruder_hint () const; virtual std::string description () const; diff --git a/src/db/unit_tests/dbHierProcessorTests.cc b/src/db/unit_tests/dbHierProcessorTests.cc index 5369eb73a..902213fa9 100644 --- a/src/db/unit_tests/dbHierProcessorTests.cc +++ b/src/db/unit_tests/dbHierProcessorTests.cc @@ -55,15 +55,15 @@ public: // .. nothing yet .. } - virtual void compute_local (db::Layout *layout, const db::shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const + virtual void compute_local (db::Layout *layout, const db::shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const { - db::shape_interactions sized_interactions = interactions; - for (db::shape_interactions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { - for (db::shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - const db::PolygonRef &ref = interactions.shape (*j); + db::shape_interactions sized_interactions = interactions; + for (db::shape_interactions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { + for (db::shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + const db::PolygonRef &ref = interactions.intruder_shape (*j); db::Polygon poly = ref.obj ().transformed (ref.trans ()); poly.size (m_dist, m_dist); - sized_interactions.add_shape (*j, db::PolygonRef (poly, layout->shape_repository ())); + sized_interactions.add_intruder_shape (*j, db::PolygonRef (poly, layout->shape_repository ())); } } BoolAndOrNotLocalOperation::compute_local (layout, sized_interactions, result, max_vertex_count, area_ratio); @@ -91,21 +91,21 @@ public: // .. nothing yet .. } - virtual void compute_local (db::Layout *layout, const db::shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const + virtual void compute_local (db::Layout *layout, const db::shape_interactions &interactions, std::unordered_set &result, size_t max_vertex_count, double area_ratio) const { - db::shape_interactions sized_interactions = interactions; - for (db::shape_interactions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { + db::shape_interactions sized_interactions = interactions; + for (db::shape_interactions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { - const db::PolygonRef &ref = interactions.shape (i->first); + const db::PolygonRef &ref = interactions.subject_shape (i->first); db::Polygon poly = ref.obj ().transformed (ref.trans ()); poly.size (m_dist / 2, m_dist / 2); - sized_interactions.add_shape (i->first, db::PolygonRef (poly, layout->shape_repository ())); + sized_interactions.add_subject_shape (i->first, db::PolygonRef (poly, layout->shape_repository ())); - for (db::shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - const db::PolygonRef &ref = interactions.shape (*j); + for (db::shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + const db::PolygonRef &ref = interactions.intruder_shape (*j); db::Polygon poly = ref.obj ().transformed (ref.trans ()); poly.size (m_dist / 2, m_dist / 2); - sized_interactions.add_shape (*j, db::PolygonRef (poly, layout->shape_repository ())); + sized_interactions.add_intruder_shape (*j, db::PolygonRef (poly, layout->shape_repository ())); } } @@ -140,15 +140,15 @@ static void normalize_layer (db::Layout &layout, unsigned int layer) } -static std::string contexts_to_s (db::Layout *layout, db::local_processor_contexts &contexts) +static std::string contexts_to_s (db::Layout *layout, db::local_processor_contexts &contexts) { std::string res; for (db::Layout::top_down_const_iterator i = layout->begin_top_down (); i != layout->end_top_down(); ++i) { - db::local_processor_contexts::iterator cc = contexts.context_map ().find (&layout->cell (*i)); + db::local_processor_contexts::iterator cc = contexts.context_map ().find (&layout->cell (*i)); if (cc != contexts.context_map ().end ()) { int index = 1; - for (db::local_processor_cell_contexts::iterator j = cc->second.begin (); j != cc->second.end (); ++j) { + for (db::local_processor_cell_contexts::iterator j = cc->second.begin (); j != cc->second.end (); ++j) { res += tl::sprintf ("%s[%d] %d insts, %d shapes (%d times)\n", layout->cell_name (*i), index, int (j->first.first.size ()), int (j->first.second.size ()), int (j->second.size ())); index += 1; } @@ -203,7 +203,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m normalize_layer (layout_org, l2); } - db::local_operation *lop = 0; + db::local_operation *lop = 0; db::BoolAndOrNotLocalOperation bool_op (mode == TMAnd || mode == TMAndSwapped); db::SelfOverlapMergeLocalOperation self_intersect_op (2); BoolAndOrNotWithSizedLocalOperation sized_bool_op (mode == TMAnd || mode == TMAndSwapped, dist); @@ -224,7 +224,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m if (single) { - db::local_processor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ())); + db::local_processor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ())); proc.set_threads (nthreads); proc.set_area_ratio (3.0); proc.set_max_vertex_count (16); @@ -232,7 +232,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m if (! context_doc) { proc.run (lop, l1, l2, lout); } else { - db::local_processor_contexts contexts; + db::local_processor_contexts contexts; proc.compute_contexts (contexts, lop, l1, l2); *context_doc = contexts_to_s (&layout_org, contexts); proc.compute_results (contexts, lop, lout); @@ -242,7 +242,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m db::Layout layout_org2 = layout_org; - db::local_processor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()), &layout_org2, &layout_org2.cell (*layout_org2.begin_top_down ())); + db::local_processor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()), &layout_org2, &layout_org2.cell (*layout_org2.begin_top_down ())); proc.set_threads (nthreads); proc.set_area_ratio (3.0); proc.set_max_vertex_count (16); @@ -250,7 +250,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m if (! context_doc) { proc.run (lop, l1, l2, lout); } else { - db::local_processor_contexts contexts; + db::local_processor_contexts contexts; proc.compute_contexts (contexts, lop, l1, l2); *context_doc = contexts_to_s (&layout_org, contexts); proc.compute_results (contexts, lop, lout); diff --git a/src/rdb/rdb/gsiDeclRdb.cc b/src/rdb/rdb/gsiDeclRdb.cc index 928dd88c9..e4ccc0267 100644 --- a/src/rdb/rdb/gsiDeclRdb.cc +++ b/src/rdb/rdb/gsiDeclRdb.cc @@ -267,9 +267,27 @@ static void scan_layer3 (rdb::Category *cat, const db::Layout &layout, unsigned rdb::scan_layer (cat, layout, layer, from_cell, levels); } -static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter) +static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat) { - rdb::scan_layer (cat, iter); + rdb::scan_layer (cat, iter, flat); +} + +static void scan_region (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Region ®ion, bool flat) +{ + std::pair it = region.begin_iter (); + rdb::scan_layer (cat, cell, trans * it.second, it.first, flat); +} + +static void scan_edges (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Edges &edges, bool flat) +{ + std::pair it = edges.begin_iter (); + rdb::scan_layer (cat, cell, trans * it.second, it.first, flat); +} + +static void scan_edge_pairs (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::EdgePairs &edge_pairs, bool flat) +{ + std::pair it; /* @@@ = edges.begin_iter (); */ + rdb::scan_layer (cat, cell, trans * it.second, it.first, flat); } Class decl_RdbCategory ("rdb", "RdbCategory", @@ -289,13 +307,41 @@ Class decl_RdbCategory ("rdb", "RdbCategory", "\n" "This method has been introduced in version 0.23." ) + - gsi::method_ext ("scan_shapes", &scan_shapes, + gsi::method_ext ("scan_shapes", &scan_shapes, gsi::arg ("iter"), gsi::arg ("flat", false), "@brief Scans the polygon or edge shapes from the shape iterator into the category\n" - "@args iter\n" "Creates RDB items for each polygon or edge shape read from the iterator and puts them into this category.\n" "A similar, but lower-level method is \\ReportDatabase#create_items with a \\RecursiveShapeIterator argument.\n" + "In contrast to \\ReportDatabase#create_items, 'scan_shapes' can also produce hierarchical databases " + "if the \\flat argument is false. In this case, the hierarchy the recursive shape iterator traverses is " + "copied into the report database using sample references.\n" "\n" - "This method has been introduced in version 0.23.\n" + "This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26.\n" + ) + + gsi::method_ext ("scan_region", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false), + "@brief Turns the given region into a hierarchical or flat report database\n" + "The exact behavior depends on the nature of the region. If the region is a hierarchical (original or deep) region " + "and the 'flat' argument is false, this method will produce a hierarchical report database in the given category. " + "The 'cell_id' parameter is ignored in this case. Sample references will be produced to supply " + "minimal instantiation information.\n" + "\n" + "If the region is a flat one or the 'flat' argument is true, the region's polygons will be produced as " + "report database items in this category and in the cell given by 'cell_id'.\n" + "\n" + "The transformation argument needs to supply the dbu-to-micron transformation.\n" + "\n" + "This method has been introduced in version 0.26.\n" + ) + + gsi::method_ext ("scan_edges", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false), + "@brief Turns the given edge collection into a hierarchical or flat report database\n" + "This method behaves like the \\scan_region method, except that is accepts an edge collection.\n" + "\n" + "This method has been introduced in version 0.26.\n" + ) + + gsi::method_ext ("scan_edge_pairs", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false), + "@brief Turns the given edge pair collection into a hierarchical or flat report database\n" + "This method behaves like the \\scan_region method, except that is accepts an edge pair collection.\n" + "\n" + "This method has been introduced in version 0.26.\n" ) + gsi::method_ext ("scan_layer", &scan_layer1, "@brief Scans a layer from a layout into this category\n" @@ -966,98 +1012,19 @@ void database_set_tag_description (rdb::Database *db, rdb::id_type tag, const st db->set_tag_description (tag, d); } -void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter) -{ - tl_assert (iter.layout ()); - double dbu = iter.layout ()->dbu (); - - for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) { - std::auto_ptr value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ())); - if (value.get ()) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (value.release ()); - } - } -} - -void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes) -{ - for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) { - std::auto_ptr value (rdb::ValueBase::create_from_shape (*s, trans)); - if (value.get ()) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (value.release ()); - } - } -} - -void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape) -{ - std::auto_ptr value (rdb::ValueBase::create_from_shape (shape, trans)); - if (value.get ()) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (value.release ()); - } -} - -void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection) -{ - typedef db::Region::const_iterator iter; - - for (iter o = collection.begin (); ! o.at_end (); ++o) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (new rdb::Value (o->transformed (trans))); - } -} - -void create_items_from_edges (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Edges &collection) -{ - typedef db::Edges::const_iterator iter; - - for (iter o = collection.begin (); ! o.at_end (); ++o) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (new rdb::Value (o->transformed (trans))); - } -} - -void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::EdgePairs &collection) -{ - typedef db::EdgePairs::const_iterator iter; - - for (iter o = collection.begin (); ! o.at_end (); ++o) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (new rdb::Value (o->transformed (trans))); - } -} - void create_items_from_polygon_array (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const std::vector &collection) { - typedef std::vector::const_iterator iter; - - for (iter o = collection.begin (); o != collection.end (); ++o) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (new rdb::Value (o->transformed (trans))); - } + rdb::create_items_from_sequence (db, cell_id, cat_id, trans, collection.begin (), collection.end ()); } void create_items_from_edge_array (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const std::vector &collection) { - typedef std::vector::const_iterator iter; - - for (iter o = collection.begin (); o != collection.end (); ++o) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (new rdb::Value (o->transformed (trans))); - } + rdb::create_items_from_sequence (db, cell_id, cat_id, trans, collection.begin (), collection.end ()); } void create_items_from_edge_pair_array (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const std::vector &collection) { - typedef std::vector::const_iterator iter; - - for (iter o = collection.begin (); o != collection.end (); ++o) { - rdb::Item *item = db->create_item (cell_id, cat_id); - item->values ().add (new rdb::Value (o->transformed (trans))); - } + rdb::create_items_from_sequence (db, cell_id, cat_id, trans, collection.begin (), collection.end ()); } static rdb::Item *create_item (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id) @@ -1081,9 +1048,8 @@ static rdb::Item *create_item_from_objects (rdb::Database *db, rdb::Cell *cell, } Class decl_ReportDatabase ("rdb", "ReportDatabase", - gsi::constructor ("new", &create_rdb, + gsi::constructor ("new", &create_rdb, gsi::arg ("name"), "@brief Creates a report database\n" - "@args name\n" "@param name The name of the database\n" "The name of the database will be used in the user interface to refer to a certain database." ) + @@ -1093,9 +1059,8 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "in a human-readable form.\n" "@return The description string\n" ) + - gsi::method ("description=", &rdb::Database::set_description, + gsi::method ("description=", &rdb::Database::set_description, gsi::arg ("desc"), "@brief Sets the databases description\n" - "@args desc\n" "@param desc The description string\n" ) + gsi::method ("generator", &rdb::Database::generator, @@ -1104,9 +1069,8 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "In a later version this should allow to rerun the tool that created the report.\n" "@return The generator string\n" ) + - gsi::method ("generator=", &rdb::Database::set_generator, + gsi::method ("generator=", &rdb::Database::set_generator, gsi::arg ("generator"), "@brief Sets the generator string\n" - "@args generator\n" "@param generator The generator string\n" ) + gsi::method ("filename", &rdb::Database::filename, @@ -1126,9 +1090,8 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "This property must be set to establish a proper hierarchical context for a hierarchical report database. " "@return The top cell name\n" ) + - gsi::method ("top_cell_name=", &rdb::Database::set_top_cell_name, + gsi::method ("top_cell_name=", &rdb::Database::set_top_cell_name, gsi::arg ("cell_name"), "@brief Sets the top cell name string\n" - "@args cell_name\n" "@param cell_name The top cell name\n" ) + gsi::method ("original_file", &rdb::Database::original_file, @@ -1136,14 +1099,12 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "The original file name is supposed to describe the file from which this report database was generated. " "@return The original file name and path\n" ) + - gsi::method ("original_file=", &rdb::Database::set_original_file, + gsi::method ("original_file=", &rdb::Database::set_original_file, gsi::arg ("path"), "@brief Sets the original file name and path\n" - "@args path\n" "@param path The path\n" ) + - gsi::method_ext ("tag_id", &database_tag_id, + gsi::method_ext ("tag_id", &database_tag_id, gsi::arg ("name"), "@brief Gets the tag ID for a given tag name\n" - "@args name\n" "@param name The tag name\n" "@return The corresponding tag ID\n" "Tags are used to tag items in the database and to specify tagged (named) values. " @@ -1153,9 +1114,8 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "\n" "\\tag_id handles system tags while \\user_tag_id handles user tags.\n" ) + - gsi::method_ext ("user_tag_id", &database_user_tag_id, + gsi::method_ext ("user_tag_id", &database_user_tag_id, gsi::arg ("name"), "@brief Gets the tag ID for a given user tag name\n" - "@args name\n" "@param name The user tag name\n" "@return The corresponding tag ID\n" "This method will always succeed and the tag will be created if it does not exist yet. " @@ -1163,23 +1123,20 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "\n" "This method has been added in version 0.24.\n" ) + - gsi::method_ext ("set_tag_description", &database_set_tag_description, + gsi::method_ext ("set_tag_description", &database_set_tag_description, gsi::arg ("tag_id"), gsi::arg ("description"), "@brief Sets the tag description for the given tag ID\n" - "@args tag_id, description\n" "@param tag_id The ID of the tag\n" "@param description The description string\n" "See \\tag_id for a details about tags.\n" ) + - gsi::method_ext ("tag_description", &database_tag_description, + gsi::method_ext ("tag_description", &database_tag_description, gsi::arg ("tag_id"), "@brief Gets the tag description for the given tag ID\n" - "@args tag_id\n" "@param tag_id The ID of the tag\n" "@return The description string\n" "See \\tag_id for a details about tags.\n" ) + - gsi::method_ext ("tag_name", &database_tag_name, + gsi::method_ext ("tag_name", &database_tag_name, gsi::arg ("tag_id"), "@brief Gets the tag name for the given tag ID\n" - "@args tag_id\n" "@param tag_id The ID of the tag\n" "@return The name of the tag\n" "See \\tag_id for a details about tags.\n\n" @@ -1188,54 +1145,45 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", gsi::iterator_ext ("each_category", &database_begin_categories, &database_end_categories, "@brief Iterates over all top-level categories\n" ) + - gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (const std::string &)) &rdb::Database::create_category, + gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (const std::string &)) &rdb::Database::create_category, gsi::arg ("name"), "@brief Creates a new top level category\n" - "@args name\n" "@param name The name of the category\n" ) + - gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (rdb::Category *, const std::string &)) &rdb::Database::create_category, + gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (rdb::Category *, const std::string &)) &rdb::Database::create_category, gsi::arg ("parent"), gsi::arg ("name"), "@brief Creates a new sub-category\n" - "@args parent,name\n" "@param parent The category under which the category should be created\n" "@param name The name of the category\n" ) + - gsi::method ("category_by_path", &rdb::Database::category_by_name, + gsi::method ("category_by_path", &rdb::Database::category_by_name, gsi::arg ("path"), "@brief Gets a category by path\n" - "@args path\n" "@param path The full path to the category starting from the top level (subcategories separated by dots)\n" "@return The (const) category object or nil if the name is not valid\n" ) + - gsi::method ("category_by_id", &rdb::Database::category_by_id, + gsi::method ("category_by_id", &rdb::Database::category_by_id, gsi::arg ("id"), "@brief Gets a category by ID\n" - "@args id\n" "@return The (const) category object or nil if the ID is not valid\n" ) + - gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &)) &rdb::Database::create_cell, + gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &)) &rdb::Database::create_cell, gsi::arg ("name"), "@brief Creates a new cell\n" - "@args name\n" "@param name The name of the cell\n" ) + - gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &, const std::string &)) &rdb::Database::create_cell, + gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &, const std::string &)) &rdb::Database::create_cell, gsi::arg ("name"), gsi::arg ("variant"), "@brief Creates a new cell, potentially as a variant for a cell with the same name\n" - "@args name, variant\n" "@param name The name of the cell\n" "@param variant The variant name of the cell\n" ) + - gsi::method ("variants", &rdb::Database::variants, + gsi::method ("variants", &rdb::Database::variants, gsi::arg ("name"), "@brief Gets the variants for a given cell name\n" - "@args name\n" "@param name The basic name of the cell\n" "@return An array of ID's representing cells that are variants for the given base name\n" ) + - gsi::method ("cell_by_qname", &rdb::Database::cell_by_qname, + gsi::method ("cell_by_qname", &rdb::Database::cell_by_qname, gsi::arg ("qname"), "@brief Returns the cell for a given qualified name\n" - "@args qname\n" "@param qname The qualified name of the cell (name plus variant name optionally)\n" "@return The cell object or nil if no such cell exists\n" ) + - gsi::method ("cell_by_id", &rdb::Database::cell_by_id, + gsi::method ("cell_by_id", &rdb::Database::cell_by_id, gsi::arg ("id"), "@brief Returns the cell for a given ID\n" - "@args id\n" "@param id The ID of the cell\n" "@return The cell object or nil if no cell with that ID exists\n" ) + @@ -1281,12 +1229,13 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "\n" "This convenience method has been added in version 0.25.\n" ) + - gsi::method_ext ("create_items", &create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"), + gsi::method_ext ("create_items", &rdb::create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"), "@brief Creates new items from a shape iterator\n" "This method takes the shapes from the given iterator and produces items from them.\n" "It accepts various kind of shapes, such as texts, polygons, boxes and paths and " - "converts them to corresponding items. " - "A similar method, which is intended for production of polygon or edge error layers is \\RdbCategory#scan_shapes.\n" + "converts them to corresponding items. This method will produce a flat version of the shapes iterated by the shape iterator. " + "A similar method, which is intended for production of polygon or edge error layers and also provides hierarchical database " + "construction is \\RdbCategory#scan_shapes.\n" "\n" "This method has been introduced in version 0.25.3.\n" "\n" @@ -1294,7 +1243,7 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "@param category_id The ID of the category to which the item is associated\n" "@param iter The iterator (a \\RecursiveShapeIterator object) from which to take the items\n" ) + - gsi::method_ext ("create_item", &create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"), + gsi::method_ext ("create_item", &rdb::create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"), "@brief Creates a new item from a single shape\n" "This method produces an item from the given shape.\n" "It accepts various kind of shapes, such as texts, polygons, boxes and paths and " @@ -1308,7 +1257,7 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "@param shape The shape to take the geometrical object from\n" "@param trans The transformation to apply\n" ) + - gsi::method_ext ("create_items", &create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"), + gsi::method_ext ("create_items", &rdb::create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"), "@brief Creates new items from a shape container\n" "This method takes the shapes from the given container and produces items from them.\n" "It accepts various kind of shapes, such as texts, polygons, boxes and paths and " @@ -1322,52 +1271,61 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "@param shapes The shape container from which to take the items\n" "@param trans The transformation to apply\n" ) + - gsi::method_ext ("create_items", &create_items_from_region, + gsi::method_ext ("create_items", &rdb::create_items_from_region, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("region"), "@brief Creates new polygon items for the given cell/category combination\n" "For each polygon in the region a single item will be created. The value of the item will be this " "polygon.\n" "A transformation can be supplied which can be used for example to convert the " "object's dimensions to micron units by scaling by the database unit.\n" "\n" + "This method will also produce a flat version of the shapes inside the region. " + "\\RdbCategory#scan_region is a similar method which also supports construction of " + "hierarchical databases from deep regions.\n" + "\n" "This method has been introduced in version 0.23.\n" "\n" - "@args cell_id, category_id, trans, polygons\n" "@param cell_id The ID of the cell to which the item is associated\n" "@param category_id The ID of the category to which the item is associated\n" "@param trans The transformation to apply\n" "@param region The region (a \\Region object) containing the polygons for which to create items\n" ) + - gsi::method_ext ("create_items", &create_items_from_edges, + gsi::method_ext ("create_items", &rdb::create_items_from_edges, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edges"), "@brief Creates new edge items for the given cell/category combination\n" "For each edge a single item will be created. The value of the item will be this " "edge.\n" "A transformation can be supplied which can be used for example to convert the " "object's dimensions to micron units by scaling by the database unit.\n" "\n" + "This method will also produce a flat version of the edges inside the edge collection. " + "\\RdbCategory#scan_edges is a similar method which also supports construction of " + "hierarchical databases from deep edge collections.\n" + "\n" "This method has been introduced in version 0.23.\n" "\n" - "@args cell_id, category_id, trans, edges\n" "@param cell_id The ID of the cell to which the item is associated\n" "@param category_id The ID of the category to which the item is associated\n" "@param trans The transformation to apply\n" "@param edges The list of edges (an \\Edges object) for which the items are created\n" ) + - gsi::method_ext ("create_items", &create_items_from_edge_pairs, + gsi::method_ext ("create_items", &rdb::create_items_from_edge_pairs, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), "@brief Creates new edge pair items for the given cell/category combination\n" "For each edge pair a single item will be created. The value of the item will be this " "edge pair.\n" "A transformation can be supplied which can be used for example to convert the " "object's dimensions to micron units by scaling by the database unit.\n" "\n" + "This method will also produce a flat version of the edge pairs inside the edge pair collection. " + "\\RdbCategory#scan_edge_pairs is a similar method which also supports construction of " + "hierarchical databases from deep edge pair collections.\n" + "\n" "This method has been introduced in version 0.23.\n" "\n" - "@args cell_id, category_id, trans, edge_pairs\n" "@param cell_id The ID of the cell to which the item is associated\n" "@param category_id The ID of the category to which the item is associated\n" "@param trans The transformation to apply\n" "@param edges The list of edge pairs (an \\EdgePairs object) for which the items are created\n" ) + - gsi::method_ext ("create_items", &create_items_from_polygon_array, + gsi::method_ext ("create_items", &create_items_from_polygon_array, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("array"), "@brief Creates new polygon items for the given cell/category combination\n" "For each polygon a single item will be created. The value of the item will be this " "polygon.\n" @@ -1376,13 +1334,12 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "\n" "This method has been introduced in version 0.23.\n" "\n" - "@args cell_id, category_id, trans, polygons\n" "@param cell_id The ID of the cell to which the item is associated\n" "@param category_id The ID of the category to which the item is associated\n" "@param trans The transformation to apply\n" "@param polygons The list of polygons for which the items are created\n" ) + - gsi::method_ext ("create_items", &create_items_from_edge_array, + gsi::method_ext ("create_items", &create_items_from_edge_array, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("array"), "@brief Creates new edge items for the given cell/category combination\n" "For each edge a single item will be created. The value of the item will be this " "edge.\n" @@ -1391,13 +1348,12 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "\n" "This method has been introduced in version 0.23.\n" "\n" - "@args cell_id, category_id, trans, edges\n" "@param cell_id The ID of the cell to which the item is associated\n" "@param category_id The ID of the category to which the item is associated\n" "@param trans The transformation to apply\n" "@param edges The list of edges for which the items are created\n" ) + - gsi::method_ext ("create_items", &create_items_from_edge_pair_array, + gsi::method_ext ("create_items", &create_items_from_edge_pair_array, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("array"), "@brief Creates new edge pair items for the given cell/category combination\n" "For each edge pair a single item will be created. The value of the item will be this " "edge pair.\n" @@ -1406,7 +1362,6 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "\n" "This method has been introduced in version 0.23.\n" "\n" - "@args cell_id, category_id, trans, edge_pairs\n" "@param cell_id The ID of the cell to which the item is associated\n" "@param category_id The ID of the category to which the item is associated\n" "@param trans The transformation to apply\n" diff --git a/src/rdb/rdb/rdb.h b/src/rdb/rdb/rdb.h index 614ec8f1e..e622d07a7 100644 --- a/src/rdb/rdb/rdb.h +++ b/src/rdb/rdb/rdb.h @@ -520,6 +520,15 @@ private: C m_value; }; +/** + * @brief Type bindings + */ +template +RDB_PUBLIC ValueBase *make_value (const T &value) +{ + return new Value (value); +} + /** * @brief A class encapsulating ValueBase pointer */ diff --git a/src/rdb/rdb/rdbUtils.cc b/src/rdb/rdb/rdbUtils.cc index d0f83eadf..059de3d5f 100644 --- a/src/rdb/rdb/rdbUtils.cc +++ b/src/rdb/rdb/rdbUtils.cc @@ -26,11 +26,14 @@ #include "dbLayout.h" #include "dbLayoutUtils.h" #include "dbRecursiveShapeIterator.h" +#include "dbRegion.h" +#include "dbEdges.h" +#include "dbEdgePairs.h" namespace rdb { -RDB_PUBLIC void +void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from, int levels) { rdb::Database *rdb = cat->database (); @@ -75,63 +78,231 @@ scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, co } - for (db::ShapeIterator shape = cell.shapes (layer).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) { - - if (shape->is_polygon () || shape->is_path () || shape->is_box ()) { - - db::Polygon poly; - shape->polygon (poly); - rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ()); - item->values ().add (new rdb::Value (poly.transformed (db::CplxTrans (layout.dbu ())))); - - } else if (shape->is_edge ()) { - - db::Edge edge; - shape->edge (edge); - rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ()); - item->values ().add (new rdb::Value (edge.transformed (db::CplxTrans (layout.dbu ())))); - - } - - } + create_items_from_shapes (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), cell.shapes (layer)); } } } -RDB_PUBLIC void -scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter) +namespace +{ + +class CreateItemsRecursiveReceiver + : public db::RecursiveShapeReceiver +{ +public: + CreateItemsRecursiveReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell) + : mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell) + { + // just in case the iterator is non-hierarchical + if (cell) { + m_cell_stack.push_back (cell); + } + } + + virtual void begin (const db::RecursiveShapeIterator *iter) + { + m_cell_stack.clear (); + + db::cell_index_type ci = iter->top_cell ()->cell_index (); + const rdb::Cell *rdb_cell = cell_for_id (iter->layout (), ci); + m_cell_stack.push_back (rdb_cell); + m_id_to_cell.insert (std::make_pair (ci, rdb_cell)); + } + + virtual void end (const db::RecursiveShapeIterator *) + { + m_cell_stack.pop_back (); + } + + virtual void enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) + { + db::cell_index_type ci = cell->cell_index (); + const rdb::Cell *rdb_cell = cell_for_id (iter->layout (), ci); + m_cell_stack.push_back (rdb_cell); + m_id_to_cell.insert (std::make_pair (ci, rdb_cell)); + + if (rdb_cell->references ().begin () == rdb_cell->references ().end ()) { + db::DCplxTrans t = m_trans * iter->trans () * m_trans.inverted (); + // TODO: get rid of the const_cast + (const_cast (rdb_cell))->references ().insert (rdb::Reference (t, m_cell_stack.front ()->id ())); + } + } + + virtual void leave_cell (const db::RecursiveShapeIterator * /*iter*/, const db::Cell * /*cell*/) + { + m_cell_stack.pop_back (); + } + + virtual new_inst_mode new_inst (const db::RecursiveShapeIterator * /*iter*/, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) + { + db::cell_index_type ci = inst.object ().cell_index (); + if (m_id_to_cell.find (ci) != m_id_to_cell.end ()) { + return NI_skip; + } else { + return NI_single; + } + } + + virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) + { + tl_assert (! m_cell_stack.empty ()); + create_item_from_shape (mp_rdb, m_cell_stack.back ()->id (), mp_cat->id (), m_trans, shape); + } + +public: + rdb::Category *mp_cat; + rdb::Database *mp_rdb; + std::vector m_cell_stack; + std::map m_id_to_cell; + db::CplxTrans m_trans; + rdb::Cell *mp_rdb_cell; + + const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci) + { + tl_assert (layout != 0); + std::string cn = layout->cell_name (ci); + const rdb::Cell *rdb_cell = mp_rdb->cell_by_qname (cn); + if (! rdb_cell) { + return mp_rdb->create_cell (cn); + } else { + return rdb_cell; + } + } +}; + +class CreateItemsFlatReceiver + : public db::RecursiveShapeReceiver +{ +public: + CreateItemsFlatReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell) + : mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell) + { + // .. nothing yet .. + } + + virtual void begin (const db::RecursiveShapeIterator *iter) + { + if (! mp_rdb_cell) { + + db::cell_index_type ci = iter->top_cell ()->cell_index (); + + tl_assert (iter->layout () != 0); + std::string cn = iter->layout ()->cell_name (ci); + mp_rdb_cell = mp_rdb->cell_by_qname (cn); + if (! mp_rdb_cell) { + mp_rdb_cell = mp_rdb->create_cell (cn); + } + + } + } + + virtual void shape (const db::RecursiveShapeIterator *iter, const db::Shape &shape, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) + { + create_item_from_shape (mp_rdb, mp_rdb_cell->id (), mp_cat->id (), m_trans * iter->trans (), shape); + } + +public: + rdb::Category *mp_cat; + rdb::Database *mp_rdb; + db::CplxTrans m_trans; + const rdb::Cell *mp_rdb_cell; +}; + +} + +void +scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat) { if (! iter.top_cell () || ! iter.layout ()) { return; } - rdb::Database *rdb = cat->database (); - if (! rdb) { + db::CplxTrans trans (iter.layout ()->dbu ()); + scan_layer (cat, 0, trans, iter, flat); +} + +void +scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat) +{ + if (! cat->database ()) { return; } - rdb::Cell *rdb_cell = rdb->create_cell (iter.layout ()->cell_name (iter.top_cell ()->cell_index ())); + std::auto_ptr rec; + if (flat) { + rec.reset (new CreateItemsFlatReceiver (cat, trans, cell)); + } else { + rec.reset (new CreateItemsRecursiveReceiver (cat, trans, cell)); + } - for (db::RecursiveShapeIterator i = iter; ! i.at_end (); ++i) { + db::RecursiveShapeIterator (iter).push (rec.get ()); +} - if (i.shape ().is_polygon () || i.shape ().is_path () || i.shape ().is_box ()) { +// ------------------------------------------------------------------------------------------------------------ - db::Polygon poly; - i.shape ().polygon (poly); - rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ()); - item->values ().add (new rdb::Value (poly.transformed (db::CplxTrans (iter.layout ()->dbu ()) * i.trans ()))); - - } else if (i.shape ().is_edge ()) { - - db::Edge edge; - i.shape ().edge (edge); - rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ()); - item->values ().add (new rdb::Value (edge.transformed (db::CplxTrans (iter.layout ()->dbu ()) * i.trans ()))); +void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter) +{ + tl_assert (iter.layout ()); + double dbu = iter.layout ()->dbu (); + for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) { + std::auto_ptr value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ())); + if (value.get ()) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (value.release ()); } + } +} +void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes) +{ + for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) { + std::auto_ptr value (rdb::ValueBase::create_from_shape (*s, trans)); + if (value.get ()) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (value.release ()); + } + } +} + +void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape) +{ + std::auto_ptr value (rdb::ValueBase::create_from_shape (shape, trans)); + if (value.get ()) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (value.release ()); + } +} + +void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection) +{ + typedef db::Region::const_iterator iter; + + for (iter o = collection.begin (); ! o.at_end (); ++o) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (new rdb::Value (o->transformed (trans))); + } +} + +void create_items_from_edges (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Edges &collection) +{ + typedef db::Edges::const_iterator iter; + + for (iter o = collection.begin (); ! o.at_end (); ++o) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (new rdb::Value (o->transformed (trans))); + } +} + +void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::EdgePairs &collection) +{ + typedef db::EdgePairs::const_iterator iter; + + for (iter o = collection.begin (); ! o.at_end (); ++o) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (new rdb::Value (o->transformed (trans))); } } diff --git a/src/rdb/rdb/rdbUtils.h b/src/rdb/rdb/rdbUtils.h index 01bade4a8..cfdfb90a2 100644 --- a/src/rdb/rdb/rdbUtils.h +++ b/src/rdb/rdb/rdbUtils.h @@ -26,12 +26,17 @@ #include "rdb.h" #include "dbTypes.h" +#include "dbTrans.h" namespace db { class Layout; class Cell; class RecursiveShapeIterator; + class Shapes; + class Region; + class Edges; + class EdgePairs; } namespace rdb @@ -52,7 +57,84 @@ RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::Layout &layout, unsign /** * @brief Scans a recursive shape iterator into a RDB category */ -RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter); +RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat = false); + +/** + * @brief Scans a recursive shape iterator into a RDB category + * + * This version allows supplying a cell and a transformation. With this information, the function can also handle + * pseudo-iterators which don't deliver the information from a layout from from a plain shape collection. + */ +RDB_PUBLIC void scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat = false); + +/** + * @brief Creates RDB items from a recursive shape iterator + * + * This function will produce items from the flattened shape iterator. The items will be stored under + * the given cell. + */ +RDB_PUBLIC void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter); + +/** + * @brief Creates RDB items from a shape collection + * + * An arbitrary transformation can be applied to translate the shapes before turning them to items. + * This transformation is useful for providing the DBU-to-micron conversion. + */ +RDB_PUBLIC void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes); + +/** + * @brief Creates RDB items from a single shape + * + * An arbitrary transformation can be applied to translate the shapes before turning them to items. + * This transformation is useful for providing the DBU-to-micron conversion. + */ +RDB_PUBLIC void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape); + +/** + * @brief Creates RDB items from a region + * + * This function will flatten the region and store the resulting items under the given cell. + * + * An arbitrary transformation can be applied to translate the shapes before turning them to items. + * This transformation is useful for providing the DBU-to-micron conversion. + */ +RDB_PUBLIC void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection); + +/** + * @brief Creates RDB items from an edge collection + * + * This function will flatten the edge collection and store the resulting items under the given cell. + * + * An arbitrary transformation can be applied to translate the shapes before turning them to items. + * This transformation is useful for providing the DBU-to-micron conversion. + */ +RDB_PUBLIC void create_items_from_edges (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Edges &collection); + +/** + * @brief Creates RDB items from an edge pair collection + * + * This function will flatten the edge pair collection and store the resulting items under the given cell. + * + * An arbitrary transformation can be applied to translate the shapes before turning them to items. + * This transformation is useful for providing the DBU-to-micron conversion. + */ +RDB_PUBLIC void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::EdgePairs &collection); + +/** + * @brief Creates RDB items from a sequence of integer-type objects + * + * An arbitrary transformation can be applied to translate the shapes before turning them to items. + * This transformation is useful for providing the DBU-to-micron conversion. + */ +template +RDB_PUBLIC void create_items_from_sequence (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const Trans &trans, Iter begin, Iter end) +{ + for (Iter o = begin; o != end; ++o) { + rdb::Item *item = db->create_item (cell_id, cat_id); + item->values ().add (rdb::make_value (o->transformed (trans))); + } +} } diff --git a/testdata/ruby/rdbTest.rb b/testdata/ruby/rdbTest.rb index 2aa57f370..4ecc4de36 100644 --- a/testdata/ruby/rdbTest.rb +++ b/testdata/ruby/rdbTest.rb @@ -769,18 +769,18 @@ class RDB_TestClass < TestBase rdb = RBA::ReportDatabase.new("neu") cat = rdb.create_category("l1") - cat.scan_shapes(c1.begin_shapes_rec(l1)) + cat.scan_shapes(c1.begin_shapes_rec(l1)) # hierarchical scan assert_equal(cat.num_items, 3) cn = [] rdb.each_cell { |c| cn << c.to_s_test } - assert_equal(cn.join(";"), "c1[]") + assert_equal(cn.join(";"), "c1[];c2[c1->r0 *1 0.01,0.02];c3[c1->r0 *1 0.021,0.041]") cn = [] rdb.each_cell { |c| cn << c.to_s_items } - assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.03;0.02,0.03;0.02,0.001),polygon: (0.01,0.021;0.01,0.051;0.031,0.051;0.031,0.021),polygon: (0.021,0.042;0.021,0.073;0.043,0.073;0.043,0.042)]") + assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.03;0.02,0.03;0.02,0.001)];c2[polygon: (0,0.001;0,0.031;0.021,0.031;0.021,0.001)];c3[polygon: (0,0.001;0,0.032;0.022,0.032;0.022,0.001)]") rdb = RBA::ReportDatabase.new("neu") cat = rdb.create_category("l1") - cat.scan_shapes(c1.begin_shapes_rec(l1)) + cat.scan_shapes(c1.begin_shapes_rec(l1), true) # flat scan assert_equal(cat.num_items, 3) cn = [] rdb.each_cell { |c| cn << c.to_s_test }