mirror of https://github.com/KLayout/klayout.git
Bugfix: a segfault happened during net cluster formation because make_path was messing up the memory layout of the cluster collections.
This commit is contained in:
parent
7e42ff83cd
commit
7d06ea83c1
|
|
@ -1004,6 +1004,17 @@ public:
|
||||||
typedef typename local_cluster<T>::id_type id_type;
|
typedef typename local_cluster<T>::id_type id_type;
|
||||||
typedef std::map<ClusterInstance, id_type> connector_map;
|
typedef std::map<ClusterInstance, id_type> connector_map;
|
||||||
|
|
||||||
|
struct ClusterInstanceInteraction
|
||||||
|
{
|
||||||
|
ClusterInstanceInteraction (size_t _cluster_id, size_t _other_cluster_id, const std::vector<db::InstElement> &_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<db::InstElement> other_path;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
*/
|
*/
|
||||||
|
|
@ -1054,8 +1065,26 @@ public:
|
||||||
* This step is postponed because doing this while the iteration happens would
|
* This step is postponed because doing this while the iteration happens would
|
||||||
* invalidate the box trees.
|
* invalidate the box trees.
|
||||||
*/
|
*/
|
||||||
void join_superclusters ()
|
void finish_cluster_to_instance_interactions ()
|
||||||
{
|
{
|
||||||
|
for (typename std::list<ClusterInstanceInteraction>::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<std::set<id_type> >::const_iterator sc = m_cm2join_sets.begin (); sc != m_cm2join_sets.end (); ++sc) {
|
for (typename std::list<std::set<id_type> >::const_iterator sc = m_cm2join_sets.begin (); sc != m_cm2join_sets.end (); ++sc) {
|
||||||
|
|
||||||
if (sc->empty ()) {
|
if (sc->empty ()) {
|
||||||
|
|
@ -1082,6 +1111,7 @@ private:
|
||||||
typedef std::list<std::set<id_type> > join_set_list;
|
typedef std::list<std::set<id_type> > join_set_list;
|
||||||
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
||||||
join_set_list m_cm2join_sets;
|
join_set_list m_cm2join_sets;
|
||||||
|
std::list<ClusterInstanceInteraction> m_ci_interactions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handles the cluster interactions between two instances or instance arrays
|
* @brief Handles the cluster interactions between two instances or instance arrays
|
||||||
|
|
@ -1184,6 +1214,10 @@ private:
|
||||||
db::ICplxTrans t2i = t2.inverted ();
|
db::ICplxTrans t2i = t2.inverted ();
|
||||||
db::ICplxTrans t21 = t1i * t2;
|
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<std::pair<size_t, size_t> > interactions;
|
||||||
|
|
||||||
for (typename db::local_clusters<T>::touching_iterator i = cl1.begin_touching (common.transformed (t1i)); ! i.at_end (); ++i) {
|
for (typename db::local_clusters<T>::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
|
// skip the test, if this cluster doesn't interact with the whole cell2
|
||||||
|
|
@ -1195,9 +1229,17 @@ private:
|
||||||
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc1.transformed (t2i)); ! j.at_end (); ++j) {
|
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc1.transformed (t2i)); ! j.at_end (); ++j) {
|
||||||
|
|
||||||
if (i->interacts (*j, t21, *mp_conn)) {
|
if (i->interacts (*j, t21, *mp_conn)) {
|
||||||
|
interactions.push_back (std::make_pair (i->id (), j->id ()));
|
||||||
|
}
|
||||||
|
|
||||||
ClusterInstance k1 = make_path (i->id (), p1);
|
}
|
||||||
ClusterInstance k2 = make_path (j->id (), p2);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<std::pair<size_t, size_t> >::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 x1 = mp_cell_clusters->find_cluster_with_connection (k1);
|
||||||
id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2);
|
id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2);
|
||||||
|
|
@ -1232,11 +1274,6 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1358,26 +1395,15 @@ private:
|
||||||
void add_single_pair (const local_cluster<T> &c1,
|
void add_single_pair (const local_cluster<T> &c1,
|
||||||
db::cell_index_type ci2, const std::vector<db::InstElement> &p2, const db::ICplxTrans &t2)
|
db::cell_index_type ci2, const std::vector<db::InstElement> &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<T> &cl2 = mp_tree->clusters_per_cell (ci2);
|
const db::local_clusters<T> &cl2 = mp_tree->clusters_per_cell (ci2);
|
||||||
|
|
||||||
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (c1.bbox ().transformed (t2.inverted ())); ! j.at_end (); ++j) {
|
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (c1.bbox ().transformed (t2.inverted ())); ! j.at_end (); ++j) {
|
||||||
|
|
||||||
if (c1.interacts (*j, t2, *mp_conn)) {
|
if (c1.interacts (*j, t2, *mp_conn)) {
|
||||||
|
m_ci_interactions.push_back (ClusterInstanceInteraction (c1.id (), j->id (), p2));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1649,19 +1675,17 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
|
||||||
todo.push_back (*c);
|
todo.push_back (*c);
|
||||||
} else {
|
} else {
|
||||||
tl_assert (! todo.empty ());
|
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 ());
|
done.insert (todo.begin (), todo.end ());
|
||||||
todo.clear ();
|
todo.clear ();
|
||||||
todo.push_back (*c);
|
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<T>::build_local_cluster (const db::Layout &layout, const db::Cell
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn)
|
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, tl::RelativeProgress &progress)
|
||||||
{
|
{
|
||||||
for (std::vector<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
|
for (std::vector<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
|
||||||
build_hier_connections (cbc, layout, layout.cell (*c), conn);
|
build_hier_connections (cbc, layout, layout.cell (*c), conn);
|
||||||
|
++progress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1850,7 +1875,7 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
|
||||||
}
|
}
|
||||||
|
|
||||||
// join local clusters which got connected by child clusters
|
// join local clusters which got connected by child clusters
|
||||||
rec->join_superclusters ();
|
rec->finish_cluster_to_instance_interactions ();
|
||||||
rec.reset (0);
|
rec.reset (0);
|
||||||
|
|
||||||
// finally connect global nets
|
// finally connect global nets
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,10 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
namespace tl {
|
||||||
|
class RelativeProgress;
|
||||||
|
}
|
||||||
|
|
||||||
namespace db {
|
namespace db {
|
||||||
|
|
||||||
class DeepLayer;
|
class DeepLayer;
|
||||||
|
|
@ -791,7 +795,7 @@ public:
|
||||||
private:
|
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_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<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn);
|
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn);
|
||||||
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn);
|
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, tl::RelativeProgress &progress);
|
||||||
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn);
|
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn);
|
||||||
|
|
||||||
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
|
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue