From 4acc4b96e21162f4da77c1c98ba5dd3341c78df4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 9 Dec 2019 21:37:02 +0100 Subject: [PATCH] First attempt to fix the issue Problem was caching which did not take into account the array nature of instances. This fix also moves the cache one level below so it is effective also when instance tree traversal happens. This might speed up things too. Needs testing. --- src/db/db/dbHierNetworkProcessor.cc | 172 +++++++++++------- src/db/db/dbHierNetworkProcessor.h | 19 +- .../unit_tests/dbHierNetworkProcessorTests.cc | 5 + 3 files changed, 129 insertions(+), 67 deletions(-) diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 1728f32d6..fdf8a492e 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1177,37 +1177,21 @@ public: */ void add (const db::Instance *i1, unsigned int /*p1*/, const db::Instance *i2, unsigned int /*p2*/) { - db::ICplxTrans t1 = i1->complex_trans (); - db::ICplxTrans t2 = i2->complex_trans (); - db::ICplxTrans t21 = t1.inverted () * t2; + std::list > ic; - InstanceToInstanceInteraction ii_key (i1->cell_index (), i2->cell_index (), t21); - - instance_interaction_cache_type::iterator ii = mp_instance_interaction_cache->find (ii_key); - if (ii != mp_instance_interaction_cache->end ()) { - - db::ICplxTrans ic_trans = t1 * ii->second.first.inverted (); - connect_clusters (ii->second.second, &ic_trans, i1->prop_id (), i2->prop_id ()); - - } else { - - std::list > &ic = mp_instance_interaction_cache->insert (std::make_pair (ii_key, std::make_pair (t1, cluster_instance_pair_list_type ()))).first->second.second; - - std::vector p; - db::ICplxTrans t; - add_pair (box_type::world (), *i1, p, t, *i2, p, t, ic); + std::vector p; + db::ICplxTrans t; + add_pair (box_type::world (), *i1, p, t, *i2, p, t, ic); #if 1 - // For debugging: ensures the instance properties are configured properly (important for cache consistency) - for (cluster_instance_pair_list_type::const_iterator i = ic.begin (); i != ic.end (); ++i) { - tl_assert (i->first.inst_prop_id () == i1->prop_id ()); - tl_assert (i->second.inst_prop_id () == i2->prop_id ()); - } + // For debugging: ensures the instance properties are configured properly (important for cache consistency) + for (cluster_instance_pair_list_type::const_iterator i = ic.begin (); i != ic.end (); ++i) { + tl_assert (i->first.inst_prop_id () == i1->prop_id ()); + tl_assert (i->second.inst_prop_id () == i2->prop_id ()); + } #endif - connect_clusters (ic); - - } + connect_clusters (ic); } /** @@ -1280,7 +1264,7 @@ private: : public InstanceToInstanceInteraction { InteractionKeyForClustersType (db::cell_index_type _ci1, db::cell_index_type _ci2, const db::ICplxTrans &_t21, const box_type &_box) - : InstanceToInstanceInteraction (_ci1, _ci2, _t21), box (_box) + : InstanceToInstanceInteraction (_ci1, 0, _ci2, 0, _t21), box (_box) { } bool operator== (const InteractionKeyForClustersType &other) const @@ -1326,7 +1310,7 @@ private: * @param p2 The instantiation path to the child cell (not including i2) * @param t2 The accumulated transformation of the path, not including i2 */ - 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, std::list > &interacting_clusters) + 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, std::list > &interacting_clusters_out) { if (is_breakout_cell (mp_breakout_cells, i1.cell_index ()) || is_breakout_cell (mp_breakout_cells, i2.cell_index ())) { return; @@ -1344,63 +1328,125 @@ private: return; } - db::ICplxTrans t1i = t1.inverted (); - db::ICplxTrans t2i = t2.inverted (); + db::ICplxTrans tt2 = t2 * i2.complex_trans (); + db::ICplxTrans tt1 = t1 * i1.complex_trans (); - for (db::CellInstArray::iterator ii1 = i1.begin_touching (common_all.transformed (t1i), mp_layout); ! ii1.at_end (); ++ii1) { + db::ICplxTrans tt21 = tt1.inverted () * tt2; + InstanceToInstanceInteraction ii_key (i1.cell_index (), i1.cell_inst ().delegate (), i2.cell_index (), i2.cell_inst ().delegate (), tt21); - db::ICplxTrans tt1 = t1 * i1.complex_trans (*ii1); - box_type ib1 = bb1.transformed (tt1); + instance_interaction_cache_type::iterator ii = mp_instance_interaction_cache->find (ii_key); + if (ii != mp_instance_interaction_cache->end ()) { + // take from cache if possible + db::ICplxTrans ic_trans = tt1 * ii->second.first.inverted (); + for (cluster_instance_pair_list_type::const_iterator ic = ii->second.second.begin (); ic != ii->second.second.end (); ++ic) { + interacting_clusters_out.push_back (*ic); + interacting_clusters_out.back ().first.transform (ic_trans); + interacting_clusters_out.back ().second.transform (ic_trans); + } + return; + } + std::list > &interacting_clusters = mp_instance_interaction_cache->insert (std::make_pair (ii_key, std::make_pair (tt1, cluster_instance_pair_list_type ()))).first->second.second; + + if (i1.size () == 1 && i2.size () == 1) { + + // single-to-single instance interactions + + // TODO: can't we just add the new item to the path and remove it later? std::vector pp1; pp1.reserve (p1.size () + 1); pp1.insert (pp1.end (), p1.begin (), p1.end ()); - pp1.push_back (ClusterInstElement (i1.cell_index (), i1.complex_trans (*ii1), i1.prop_id ())); + pp1.push_back (ClusterInstElement (i1.cell_index (), i1.complex_trans (), i1.prop_id ())); - for (db::CellInstArray::iterator ii2 = i2.begin_touching (ib1.transformed (t2i), mp_layout); ! ii2.at_end (); ++ii2) { + // skip interactions between identical instances (duplicate instance removal) + if (i1.cell_index () != i2.cell_index () || tt1 != tt2) { - db::ICplxTrans tt2 = t2 * i2.complex_trans (*ii2); - if (i1.cell_index () == i2.cell_index () && tt1 == tt2) { - // skip interactions between identical instances (duplicate instance removal) - continue; + std::vector pp2; + pp2.reserve (p2.size () + 1); + pp2.insert (pp2.end (), p2.begin (), p2.end ()); + pp2.push_back (ClusterInstElement (i2.cell_index (), i2.complex_trans (), i2.prop_id ())); + + add_single_pair (common_all, i1.cell_index (), pp1, tt1, i2.cell_index (), pp2, tt2, interacting_clusters); + + // dive into cell of i2 + const db::Cell &cell2 = mp_layout->cell (i2.cell_index ()); + for (db::Cell::touching_iterator jj2 = cell2.begin_touching (common_all.transformed (tt2.inverted ())); ! jj2.at_end (); ++jj2) { + add_pair (common_all, i1, p1, t1, *jj2, pp2, tt2, interacting_clusters); } - box_type ib2 = bb2.transformed (tt2); + } - box_type common12 = ib1 & ib2 & common; + // dive into cell of i1 + const db::Cell &cell1 = mp_layout->cell (i1.cell_index ()); + for (db::Cell::touching_iterator jj1 = cell1.begin_touching (common_all.transformed (tt1.inverted ())); ! jj1.at_end (); ++jj1) { + add_pair (common_all, *jj1, pp1, tt1, i2, p2, t2, interacting_clusters); + } - if (! common12.empty ()) { + } else { - std::vector pp2; - pp2.reserve (p2.size () + 1); - pp2.insert (pp2.end (), p2.begin (), p2.end ()); - pp2.push_back (ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ())); + // array interactions - add_single_pair (common12, i1.cell_index (), pp1, tt1, i2.cell_index (), pp2, tt2, interacting_clusters); + db::ICplxTrans t1i = t1.inverted (); + db::ICplxTrans t2i = t2.inverted (); - // dive into cell of ii2 - const db::Cell &cell2 = mp_layout->cell (i2.cell_index ()); - for (db::Cell::touching_iterator jj2 = cell2.begin_touching (common12.transformed (tt2.inverted ())); ! jj2.at_end (); ++jj2) { - add_pair (common12, i1, p1, t1, *jj2, pp2, tt2, interacting_clusters); + for (db::CellInstArray::iterator ii1 = i1.begin_touching (common_all.transformed (t1i), mp_layout); ! ii1.at_end (); ++ii1) { + + db::ICplxTrans tt1 = t1 * i1.complex_trans (*ii1); + box_type ib1 = bb1.transformed (tt1); + + std::vector pp1; + pp1.reserve (p1.size () + 1); + pp1.insert (pp1.end (), p1.begin (), p1.end ()); + pp1.push_back (ClusterInstElement (i1.cell_index (), i1.complex_trans (*ii1), i1.prop_id ())); + + for (db::CellInstArray::iterator ii2 = i2.begin_touching (ib1.transformed (t2i), mp_layout); ! ii2.at_end (); ++ii2) { + + db::ICplxTrans tt2 = t2 * i2.complex_trans (*ii2); + if (i1.cell_index () == i2.cell_index () && tt1 == tt2) { + // skip interactions between identical instances (duplicate instance removal) + continue; + } + + box_type ib2 = bb2.transformed (tt2); + + box_type common12 = ib1 & ib2 & common; + + if (! common12.empty ()) { + + std::vector pp2; + pp2.reserve (p2.size () + 1); + pp2.insert (pp2.end (), p2.begin (), p2.end ()); + pp2.push_back (ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ())); + + add_single_pair (common12, i1.cell_index (), pp1, tt1, i2.cell_index (), pp2, tt2, interacting_clusters); + + // dive into cell of ii2 + const db::Cell &cell2 = mp_layout->cell (i2.cell_index ()); + for (db::Cell::touching_iterator jj2 = cell2.begin_touching (common12.transformed (tt2.inverted ())); ! jj2.at_end (); ++jj2) { + add_pair (common12, i1, p1, t1, *jj2, pp2, tt2, interacting_clusters); + } + + } + + } + + box_type common1 = ib1 & b2 & common; + + if (! common1.empty ()) { + + // dive into cell of ii1 + const db::Cell &cell1 = mp_layout->cell (i1.cell_index ()); + for (db::Cell::touching_iterator jj1 = cell1.begin_touching (common1.transformed (tt1.inverted ())); ! jj1.at_end (); ++jj1) { + add_pair (common1, *jj1, pp1, tt1, i2, p2, t2, interacting_clusters); } } } - box_type common1 = ib1 & b2 & common; - - if (! common1.empty ()) { - - // dive into cell of ii1 - const db::Cell &cell1 = mp_layout->cell (i1.cell_index ()); - for (db::Cell::touching_iterator jj1 = cell1.begin_touching (common1.transformed (tt1.inverted ())); ! jj1.at_end (); ++jj1) { - add_pair (common1, *jj1, pp1, tt1, i2, p2, t2, interacting_clusters); - } - - } - } + + interacting_clusters_out.insert (interacting_clusters_out.end (), interacting_clusters.begin (), interacting_clusters.end ()); } /** diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index a47e93bd8..3c90dafdb 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -739,13 +739,15 @@ typedef std::list > cluster_instance */ struct InstanceToInstanceInteraction { - InstanceToInstanceInteraction (db::cell_index_type _ci1, db::cell_index_type _ci2, const db::ICplxTrans &_t21) - : ci1 (_ci1), ci2 (_ci2), t21 (_t21) + InstanceToInstanceInteraction (db::cell_index_type _ci1, const db::ArrayBase *_array1, db::cell_index_type _ci2, const db::ArrayBase *_array2, const db::ICplxTrans &_t21) + : ci1 (_ci1), ci2 (_ci2), array1 (_array1), array2 (_array2), t21 (_t21) { } bool operator== (const InstanceToInstanceInteraction &other) const { - return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21); + static const db::array_base_ptr_cmp_f arr_less; + return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21) && + (array1 == 0) == (array2 == 0) && array1 != 0 && ! arr_less (array1, array2) && ! arr_less (array2, array1); } bool operator< (const InstanceToInstanceInteraction &other) const @@ -759,10 +761,19 @@ struct InstanceToInstanceInteraction if (! t21.equal (other.t21)) { return t21.less (other.t21); } - return false; + if ((array1 == 0) != (array2 == 0)) { + return (array1 == 0) < (array2 == 0); + } + if (array1 != 0) { + static const db::array_base_ptr_cmp_f arr_less; + return arr_less (array1, array2); + } else { + return false; + } } db::cell_index_type ci1, ci2; + const db::ArrayBase *array1, *array2; db::ICplxTrans t21; }; diff --git a/src/db/unit_tests/dbHierNetworkProcessorTests.cc b/src/db/unit_tests/dbHierNetworkProcessorTests.cc index 22575f670..07ca63197 100644 --- a/src/db/unit_tests/dbHierNetworkProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetworkProcessorTests.cc @@ -1270,3 +1270,8 @@ TEST(117_HierClusters) run_hc_test_with_backannotation (_this, "hc_test_l17.gds", "hc_test_au17b.gds"); } +TEST(118_HierClustersMeanderArrays) +{ + run_hc_test (_this, "meander.gds.gz", "meander_au1.gds"); + run_hc_test_with_backannotation (_this, "meander.gds.gz", "meander_au2.gds"); +}