From 7d06ea83c19f036979288ec57689fa1afb254031 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 28 Jan 2019 21:29:34 +0100 Subject: [PATCH] Bugfix: a segfault happened during net cluster formation because make_path was messing up the memory layout of the cluster collections. --- src/db/db/dbHierNetworkProcessor.cc | 141 ++++++++++++++++------------ src/db/db/dbHierNetworkProcessor.h | 6 +- 2 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index f9a9f4d2e..d33a5631f 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1004,6 +1004,17 @@ public: typedef typename local_cluster::id_type id_type; typedef std::map connector_map; + struct ClusterInstanceInteraction + { + ClusterInstanceInteraction (size_t _cluster_id, size_t _other_cluster_id, const std::vector &_other_path) + : cluster_id (_cluster_id), other_cluster_id (_other_cluster_id), other_path (_other_path) + { } + + size_t cluster_id; + size_t other_cluster_id; + std::vector other_path; + }; + /** * @brief Constructor */ @@ -1054,8 +1065,26 @@ public: * This step is postponed because doing this while the iteration happens would * invalidate the box trees. */ - void join_superclusters () + void finish_cluster_to_instance_interactions () { + for (typename std::list::const_iterator ii = m_ci_interactions.begin (); ii != m_ci_interactions.end (); ++ii) { + + ClusterInstance other_key = make_path (ii->other_cluster_id, ii->other_path); + + id_type other = mp_cell_clusters->find_cluster_with_connection (other_key); + if (other > 0) { + + // we found a child cluster that connects two clusters on our own level: + // we must join them into one, but not now. We're still iterating and + // would invalidate the box trees. So keep this now and combine the clusters later. + mark_to_join (other, ii->cluster_id); + + } else { + mp_cell_clusters->add_connection (ii->cluster_id, other_key); + } + + } + for (typename std::list >::const_iterator sc = m_cm2join_sets.begin (); sc != m_cm2join_sets.end (); ++sc) { if (sc->empty ()) { @@ -1082,6 +1111,7 @@ private: typedef std::list > join_set_list; std::map m_cm2join_map; join_set_list m_cm2join_sets; + std::list m_ci_interactions; /** * @brief Handles the cluster interactions between two instances or instance arrays @@ -1184,6 +1214,10 @@ private: db::ICplxTrans t2i = t2.inverted (); db::ICplxTrans t21 = t1i * t2; + // NOTE: make_path may disturb the iteration (because of modification), hence + // we first collect and then process the interactions. + std::vector > interactions; + for (typename db::local_clusters::touching_iterator i = cl1.begin_touching (common.transformed (t1i)); ! i.at_end (); ++i) { // skip the test, if this cluster doesn't interact with the whole cell2 @@ -1195,48 +1229,51 @@ private: for (typename db::local_clusters::touching_iterator j = cl2.begin_touching (bc1.transformed (t2i)); ! j.at_end (); ++j) { if (i->interacts (*j, t21, *mp_conn)) { - - ClusterInstance k1 = make_path (i->id (), p1); - ClusterInstance k2 = make_path (j->id (), p2); - - id_type x1 = mp_cell_clusters->find_cluster_with_connection (k1); - id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2); - - if (x1 == 0) { - - if (x2 == 0) { - - id_type connector = mp_cell_clusters->insert_dummy (); - mp_cell_clusters->add_connection (connector, k1); - mp_cell_clusters->add_connection (connector, k2); - - } else { - mp_cell_clusters->add_connection (x2, k1); - } - - } else if (x2 == 0) { - - mp_cell_clusters->add_connection (x1, k2); - - } else if (x1 != x2) { - - // for instance-to-instance interactions the number of connections is more important for the - // cost of the join operation: make the one with more connections the target - if (mp_cell_clusters->connections_for_cluster (x1).size () < mp_cell_clusters->connections_for_cluster (x2).size ()) { - std::swap (x1, x2); - } - - mp_cell_clusters->join_cluster_with (x1, x2); - mp_cell_clusters->remove_cluster (x2); - - } - + interactions.push_back (std::make_pair (i->id (), j->id ())); } } } + 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); + + id_type x1 = mp_cell_clusters->find_cluster_with_connection (k1); + id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2); + + if (x1 == 0) { + + if (x2 == 0) { + + id_type connector = mp_cell_clusters->insert_dummy (); + mp_cell_clusters->add_connection (connector, k1); + mp_cell_clusters->add_connection (connector, k2); + + } else { + mp_cell_clusters->add_connection (x2, k1); + } + + } else if (x2 == 0) { + + mp_cell_clusters->add_connection (x1, k2); + + } else if (x1 != x2) { + + // for instance-to-instance interactions the number of connections is more important for the + // cost of the join operation: make the one with more connections the target + if (mp_cell_clusters->connections_for_cluster (x1).size () < mp_cell_clusters->connections_for_cluster (x2).size ()) { + std::swap (x1, x2); + } + + mp_cell_clusters->join_cluster_with (x1, x2); + mp_cell_clusters->remove_cluster (x2); + + } + + } } /** @@ -1358,26 +1395,15 @@ private: void add_single_pair (const local_cluster &c1, db::cell_index_type ci2, const std::vector &p2, const db::ICplxTrans &t2) { + // NOTE: make_path may disturb the iteration (because of modification), hence + // we first collect and then process the interactions. + const db::local_clusters &cl2 = mp_tree->clusters_per_cell (ci2); for (typename db::local_clusters::touching_iterator j = cl2.begin_touching (c1.bbox ().transformed (t2.inverted ())); ! j.at_end (); ++j) { if (c1.interacts (*j, t2, *mp_conn)) { - - ClusterInstance k2 = make_path (j->id (), p2); - - id_type other = mp_cell_clusters->find_cluster_with_connection (k2); - if (other > 0) { - - // we found a child cluster that connects two clusters on our own level: - // we must join them into one, but not now. We're still iterating and - // would invalidate the box trees. So keep this now and combine the clusters later. - mark_to_join (other, c1.id ()); - - } else { - mp_cell_clusters->add_connection (c1.id (), k2); - } - + m_ci_interactions.push_back (ClusterInstanceInteraction (c1.id (), j->id (), p2)); } } @@ -1649,19 +1675,17 @@ hier_clusters::do_build (cell_clusters_box_converter &cbc, const db::Layou todo.push_back (*c); } else { tl_assert (! todo.empty ()); - build_hier_connections_for_cells (cbc, layout, todo, conn); + build_hier_connections_for_cells (cbc, layout, todo, conn, progress); done.insert (todo.begin (), todo.end ()); todo.clear (); todo.push_back (*c); } - ++progress; - } } - build_hier_connections_for_cells (cbc, layout, todo, conn); + build_hier_connections_for_cells (cbc, layout, todo, conn, progress); } } @@ -1681,10 +1705,11 @@ hier_clusters::build_local_cluster (const db::Layout &layout, const db::Cell template void -hier_clusters::build_hier_connections_for_cells (cell_clusters_box_converter &cbc, const db::Layout &layout, const std::vector &cells, const db::Connectivity &conn) +hier_clusters::build_hier_connections_for_cells (cell_clusters_box_converter &cbc, const db::Layout &layout, const std::vector &cells, const db::Connectivity &conn, tl::RelativeProgress &progress) { for (std::vector::const_iterator c = cells.begin (); c != cells.end (); ++c) { build_hier_connections (cbc, layout, layout.cell (*c), conn); + ++progress; } } @@ -1850,7 +1875,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c } // join local clusters which got connected by child clusters - rec->join_superclusters (); + rec->finish_cluster_to_instance_interactions (); rec.reset (0); // finally connect global nets diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index 535d18752..d34d0b7dd 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -34,6 +34,10 @@ #include #include +namespace tl { + class RelativeProgress; +} + namespace db { class DeepLayer; @@ -791,7 +795,7 @@ public: private: void build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn); void build_hier_connections (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn); - void build_hier_connections_for_cells (cell_clusters_box_converter &cbc, const db::Layout &layout, const std::vector &cells, const db::Connectivity &conn); + void build_hier_connections_for_cells (cell_clusters_box_converter &cbc, const db::Layout &layout, const std::vector &cells, const db::Connectivity &conn, tl::RelativeProgress &progress); void do_build (cell_clusters_box_converter &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn); std::map > m_per_cell_clusters;