diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 6a455f3d3..2ecf41291 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -60,6 +60,13 @@ template void insert_transformed (db::Layout & /* shapes.insert (s.transformed (t)); } +// ------------------------------------------------------------------------------ + +static bool is_breakout_cell (const std::set *breakout_cells, db::cell_index_type ci) +{ + return breakout_cells && breakout_cells->find (ci) != breakout_cells->end (); +} + // ------------------------------------------------------------------------------ // Connectivity implementation @@ -1159,8 +1166,8 @@ public: /** * @brief Constructor */ - hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters &cell_clusters, hier_clusters &tree, const cell_clusters_box_converter &cbc, const db::Connectivity &conn) - : mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn) + hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters &cell_clusters, hier_clusters &tree, const cell_clusters_box_converter &cbc, const db::Connectivity &conn, const std::set *breakout_cells) + : mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn), mp_breakout_cells (breakout_cells) { mp_cell_clusters = &cell_clusters; } @@ -1180,9 +1187,7 @@ public: */ void finish (const db::Instance *i, unsigned int /*p1*/) { - if (i->size () > 1) { - add_single_inst (*i); - } + add_single_inst (*i); } /** @@ -1243,16 +1248,51 @@ public: } private: + struct InteractionKeyType + { + InteractionKeyType (db::cell_index_type _ci1, db::cell_index_type _ci2, const db::ICplxTrans &_t21, const box_type &_box) + : ci1 (_ci1), ci2 (_ci2), t21 (_t21), box (_box) + { } + + bool operator== (const InteractionKeyType &other) const + { + return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21) && box == other.box; + } + + bool operator< (const InteractionKeyType &other) const + { + if (ci1 != other.ci1) { + return ci1 < other.ci1; + } + if (ci2 != other.ci2) { + return ci2 < other.ci2; + } + if (! t21.equal (other.t21)) { + return t21.less (other.t21); + } + if (box != other.box) { + return box < other.box; + } + return false; + } + + db::cell_index_type ci1, ci2; + db::ICplxTrans t21; + box_type box; + }; + const db::Layout *mp_layout; const db::Cell *mp_cell; db::connected_clusters *mp_cell_clusters; hier_clusters *mp_tree; const cell_clusters_box_converter *mp_cbc; const db::Connectivity *mp_conn; + const std::set *mp_breakout_cells; typedef std::list > join_set_list; std::map m_cm2join_map; join_set_list m_cm2join_sets; std::list m_ci_interactions; + std::map > > m_interaction_cache; /** * @brief Handles the cluster interactions between two instances or instance arrays @@ -1266,6 +1306,10 @@ private: */ void add_pair (const box_type &common, const db::Instance &i1, const std::vector &p1, const db::ICplxTrans &t1, const db::Instance &i2, const std::vector &p2, const db::ICplxTrans &t2) { + if (is_breakout_cell (mp_breakout_cells, i1.cell_index ()) || is_breakout_cell (mp_breakout_cells, i2.cell_index ())) { + return; + } + box_type bb1 = (*mp_cbc) (i1.cell_index ()); box_type b1 = i1.cell_inst ().bbox (*mp_cbc).transformed (t1); @@ -1351,38 +1395,62 @@ private: db::cell_index_type ci1, const std::vector &p1, const db::ICplxTrans &t1, db::cell_index_type ci2, const std::vector &p2, const db::ICplxTrans &t2) { - const db::Cell &cell2 = mp_layout->cell (ci2); - - const db::local_clusters &cl1 = mp_tree->clusters_per_cell (ci1); - const db::local_clusters &cl2 = mp_tree->clusters_per_cell (ci2); + if (is_breakout_cell (mp_breakout_cells, ci1) || is_breakout_cell (mp_breakout_cells, ci2)) { + return; + } db::ICplxTrans t1i = t1.inverted (); db::ICplxTrans t2i = t2.inverted (); db::ICplxTrans t21 = t1i * t2; + box_type common2 = common.transformed (t2i); + // NOTE: make_path may disturb the iteration (because of modification), hence // we first collect and then process the interactions. - std::vector > interactions; + const std::vector > *interactions; - for (typename db::local_clusters::touching_iterator i = cl1.begin_touching (common.transformed (t1i)); ! i.at_end (); ++i) { + InteractionKeyType ikey (ci1, ci2, t21, common2); - // skip the test, if this cluster doesn't interact with the whole cell2 - if (! i->interacts (cell2, t21, *mp_conn)) { - continue; - } + typename std::map > >::const_iterator ici = m_interaction_cache.find (ikey); + if (ici != m_interaction_cache.end ()) { - box_type bc1 = common & i->bbox ().transformed (t1); - for (typename db::local_clusters::touching_iterator j = cl2.begin_touching (bc1.transformed (t2i)); ! j.at_end (); ++j) { + interactions = &ici->second; + + } else { + + const db::Cell &cell2 = mp_layout->cell (ci2); + + const db::local_clusters &cl1 = mp_tree->clusters_per_cell (ci1); + const db::local_clusters &cl2 = mp_tree->clusters_per_cell (ci2); + + std::vector > new_interactions; + db::ICplxTrans t12 = t2i * t1; + + for (typename db::local_clusters::touching_iterator i = cl1.begin_touching (common2.transformed (t21)); ! i.at_end (); ++i) { + + // skip the test, if this cluster doesn't interact with the whole cell2 + if (! i->interacts (cell2, t21, *mp_conn)) { + continue; + } + + box_type bc2 = (common2 & i->bbox ().transformed (t12)); + for (typename db::local_clusters::touching_iterator j = cl2.begin_touching (bc2); ! j.at_end (); ++j) { + + if (i->interacts (*j, t21, *mp_conn)) { + new_interactions.push_back (std::make_pair (i->id (), j->id ())); + } - if (i->interacts (*j, t21, *mp_conn)) { - interactions.push_back (std::make_pair (i->id (), j->id ())); } } + std::vector > &out = m_interaction_cache [ikey]; + out = new_interactions; + interactions = &out; + } - for (std::vector >::const_iterator ii = interactions.begin (); ii != interactions.end (); ++ii) { + for (std::vector >::const_iterator ii = interactions->begin (); ii != interactions->end (); ++ii) { ClusterInstance k1 = make_path (ii->first, p1); ClusterInstance k2 = make_path (ii->second, p2); @@ -1427,6 +1495,10 @@ private: */ void add_single_inst (const db::Instance &i) { + if (is_breakout_cell (mp_breakout_cells, i.cell_index ())) { + return; + } + box_type bb = (*mp_cbc) (i.cell_index ()); const db::Cell &cell = mp_layout->cell (i.cell_index ()); @@ -1494,6 +1566,10 @@ private: */ void add_pair (const local_cluster &c1, const db::Instance &i2, const std::vector &p2, const db::ICplxTrans &t2) { + if (is_breakout_cell (mp_breakout_cells, i2.cell_index ())) { + return; + } + box_type b1 = c1.bbox (); box_type bb2 = (*mp_cbc) (i2.cell_index ()); @@ -1541,6 +1617,10 @@ private: void add_single_pair (const local_cluster &c1, db::cell_index_type ci2, const std::vector &p2, const db::ICplxTrans &t2) { + if (is_breakout_cell (mp_breakout_cells, ci2)) { + return; + } + // NOTE: make_path may disturb the iteration (because of modification), hence // we first collect and then process the interactions. @@ -1950,11 +2030,6 @@ private: } -static bool is_breakout_cell (const std::set *breakout_cells, db::cell_index_type ci) -{ - return breakout_cells && breakout_cells->find (ci) != breakout_cells->end (); -} - template void hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set *breakout_cells) @@ -1969,7 +2044,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c // NOTE: this is a receiver for both the child-to-child and // local to child interactions. - std::auto_ptr > rec (new hc_receiver (layout, cell, local, *this, cbc, conn)); + std::auto_ptr > rec (new hc_receiver (layout, cell, local, *this, cbc, conn, breakout_cells)); cell_inst_clusters_box_converter cibc (cbc); // The box scanner needs pointers so we have to first store the instances