From 87e658acf01e4fa2b2ba0b1a870bb939cddd17a3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 15 Dec 2019 00:48:11 +0100 Subject: [PATCH] WIP: finalized refactoring. --- src/db/db/dbHierNetworkProcessor.cc | 408 ++-------------------------- src/db/db/dbHierNetworkProcessor.h | 16 +- src/db/db/dbNetlistExtractor.cc | 5 +- 3 files changed, 28 insertions(+), 401 deletions(-) diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 1d9d5b253..7af394f59 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1189,7 +1189,7 @@ public: */ void finish (const db::Instance *i, unsigned int /*p1*/) { - add_single_inst (*i); + consider_single_inst (*i); } /** @@ -1295,161 +1295,6 @@ private: std::map > > m_interaction_cache_for_clusters; instance_interaction_cache_type *mp_instance_interaction_cache; -#if 0 // @@@ - /** - * @brief Handles the cluster interactions between two instances or instance arrays - * @param common The region under investigation (seen from the top level) - * @param i1 The index of the child cell 1 - * @param p1 The instantiation path to the child cell (not including i1) - * @param t1 The accumulated transformation of the path, not including i1 - * @param i2 The index of the child cell 2 - * @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_out) - { - 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); - - box_type bb2 = (*mp_cbc) (i2.cell_index ()); - box_type b2 = i2.cell_inst ().bbox (*mp_cbc).transformed (t2); - - box_type common_all = common & b1 & b2; - - if (common_all.empty ()) { - return; - } - - db::ICplxTrans tt2 = t2 * i2.complex_trans (); - db::ICplxTrans tt1 = t1 * i1.complex_trans (); - - db::ICplxTrans tt21 = tt1.inverted () * tt2; - InstanceToInstanceInteraction ii_key (i1.cell_index (), i1.cell_inst ().delegate (), i2.cell_index (), i2.cell_inst ().delegate (), tt21); - -#if 0 // @@@ - 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 - --> problem: cluster pairs need to be relative to the initial cell, hence we can't cache the target cluster. only the source one!!! - for (cluster_instance_pair_list_type::const_iterator ic = ii->second.second.begin (); ic != ii->second.second.end (); ++ic) { - interacting_clusters_out.push_back (std::pair ()); - interacting_clusters_out.back ().first = make_path (ic->first.id (), p1); - interacting_clusters_out.back ().second = make_path (ic->second.id (), p2); - } - 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; - -#endif - - std::list > interacting_clusters; // @@@ - - if (false /*@@@*/&& 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 (), i1.prop_id ())); - - // skip interactions between identical instances (duplicate instance removal) - if (i1.cell_index () != i2.cell_index () || tt1 != tt2) { - - 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); - } - - } - - // 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); - } - - } else { - - // array interactions - - db::ICplxTrans t1i = t1.inverted (); - db::ICplxTrans t2i = t2.inverted (); - - 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); - } - - } - - } - - } - - interacting_clusters_out.insert (interacting_clusters_out.end (), interacting_clusters.begin (), interacting_clusters.end ()); - } -#endif - /** * @brief Investigate a pair of instances * @@ -1500,7 +1345,7 @@ private: if (ii != mp_instance_interaction_cache->end ()) { // use cached interactions - interacting_clusters = ii->second.second; + interacting_clusters = ii->second; for (std::list >::iterator i = interacting_clusters.begin (); i != interacting_clusters.end (); ++i) { // translate the property IDs i->first.set_inst_prop_id (i1.prop_id ()); @@ -1518,7 +1363,7 @@ private: db::ICplxTrans t1i = t1.inverted (); db::ICplxTrans t2i = t2.inverted (); - // @@@ optimize for single inst? + // TODO: optimize for single inst? for (db::CellInstArray::iterator ii1 = i1element.at_end () ? i1.begin_touching (common_all.transformed (t1i), mp_layout) : i1element; ! ii1.at_end (); ++ii1) { db::ICplxTrans i1t = i1.complex_trans (*ii1); @@ -1594,99 +1439,20 @@ private: } - std::pair &cached = (*mp_instance_interaction_cache) [ii_key]; - cached.first = i1.complex_trans (); // @@@ remove or twofold transformation - cached.second = interacting_clusters; + cluster_instance_pair_list_type &cached = (*mp_instance_interaction_cache) [ii_key]; + cached = interacting_clusters; // normalize transformations in cache db::ICplxTrans i1ti = i1t.inverted (), i2ti = i2t.inverted (); - for (std::list >::iterator i = cached.second.begin (); i != cached.second.end (); ++i) { + for (std::list >::iterator i = cached.begin (); i != cached.end (); ++i) { i->first.transform (i1ti); i->second.transform (i2ti); } } /** - * @brief Handles the cluster interactions between two specific instances - * @param common The region under investigation (seen from the top level) - * @param ci1 The cell index of the child cell 1 - * @param p1 The instantiation path to the child cell (last element is the instance to ci1) - * @param t1 The accumulated transformation of the path p1 - * @param ci2 The cell index of the child cell 2 - * @param p2 The instantiation path to the child cell (last element is the instance to ci2) - * @param t2 The accumulated transformation of the path p2 + * @brief Computes a list of interacting clusters for two instances */ - // @@@ remove - void add_single_pair (const box_type &common, - 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, - cluster_instance_pair_list_type &interacting_clusters) - { - 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. - const std::vector > *interactions; - - InteractionKeyForClustersType ikey (ci1, ci2, t21, common2); - - typename std::map > >::const_iterator ici = m_interaction_cache_for_clusters.find (ikey); - if (ici != m_interaction_cache_for_clusters.end ()) { - - 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 ())); - } - - } - - } - - std::vector > &out = m_interaction_cache_for_clusters [ikey]; - out = new_interactions; - interactions = &out; - - } - - 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); - - interacting_clusters.push_back (std::make_pair (k1, k2)); - - } - } - const std::vector > & compute_instance_interactions (const box_type &common, db::cell_index_type ci1, const db::ICplxTrans &t1, @@ -1746,7 +1512,7 @@ private: /** * @brief Single instance treatment */ - void add_single_inst (const db::Instance &i) + void consider_single_inst (const db::Instance &i) { if (is_breakout_cell (mp_breakout_cells, i.cell_index ())) { return; @@ -1981,18 +1747,11 @@ private: } /** - * @brief Makes a valid path to a child cluster + * @brief Makes cluster connections from all parents of a cell into this cell and to the given cluster * - * Cluster connections can only cross one level of hierarchy. This method - * creates necessary dummy entries for the given path. + * After calling this method, the cluster instance in ci is guaranteed to have connections from all + * parent cells. One of these connections represents the instance ci. */ - // @@@ remove - ClusterInstance make_path (id_type id, const std::vector &path) const - { - return mp_tree->make_path (*mp_layout, *mp_cell, id, path); - } - - // @@@ void propagate_cluster_inst (ClusterInstance &ci, db::cell_index_type pci, const db::ICplxTrans &trans, db::properties_id_type prop_id) const { size_t id_new = mp_tree->propagate_cluster_inst (*mp_layout, *mp_cell, ci, pci, true); @@ -2142,134 +1901,6 @@ hier_clusters::propagate_cluster_inst (const db::Layout &layout, const db::Ce return id_new; } -template -ClusterInstance -hier_clusters::make_path (const db::Layout &layout, const db::Cell &cell, size_t id, const std::vector &path) -{ - std::vector::const_iterator p = path.end (); - tl_assert (p != path.begin ()); - - while (true) { - - --p; - - ClusterInstance ci (id, p->inst_cell_index (), p->inst_trans (), p->inst_prop_id ()); - if (p == path.begin ()) { - - // if we're attaching to a child which is root yet, we need to promote the - // cluster to the parent in all places - connected_clusters &child_cc = clusters_per_cell (p->inst_cell_index ()); - if (child_cc.is_root (id)) { - - std::set > seen; // to avoid duplicate connections - - const db::Cell &child_cell = layout.cell (p->inst_cell_index ()); - for (db::Cell::parent_inst_iterator pi = child_cell.begin_parent_insts (); ! pi.at_end (); ++pi) { - - db::Instance child_inst = pi->child_inst (); - - connected_clusters &parent_cc = clusters_per_cell (pi->parent_cell_index ()); - for (db::CellInstArray::iterator pii = child_inst.begin (); ! pii.at_end (); ++pii) { - - ClusterInstance ci2 (id, child_inst.cell_index (), child_inst.complex_trans (*pii), child_inst.prop_id ()); - if ((cell.cell_index () != pi->parent_cell_index () || ci != ci2) && seen.find (std::make_pair (pi->parent_cell_index (), ci2)) == seen.end ()) { - - size_t id_dummy; - - const typename db::local_cluster::global_nets &gn = child_cc.cluster_by_id (id).get_global_nets (); - if (gn.empty ()) { - id_dummy = parent_cc.insert_dummy (); - } else { - local_cluster *lc = parent_cc.insert (); - lc->set_global_nets (gn); - id_dummy = lc->id (); - } - - parent_cc.add_connection (id_dummy, ci2); - seen.insert (std::make_pair (pi->parent_cell_index (), ci2)); - - } - - } - - } - - child_cc.reset_root (id); - - } - - return ci; - - } - - db::cell_index_type pci = p [-1].inst_cell_index (); - connected_clusters &target_cc = clusters_per_cell (pci); - size_t parent_cluster = target_cc.find_cluster_with_connection (ci); - - if (parent_cluster > 0) { - - // taken parent - id = parent_cluster; - - } else { - - size_t id_new = 0; - - // if we're attaching to a child which is root yet, we need to promote the - // cluster to the parent in all places - connected_clusters &child_cc = clusters_per_cell (p->inst_cell_index ()); - if (child_cc.is_root (id)) { - - std::set > seen; // to avoid duplicate connections - - const db::Cell &child_cell = layout.cell (p->inst_cell_index ()); - for (db::Cell::parent_inst_iterator pi = child_cell.begin_parent_insts (); ! pi.at_end (); ++pi) { - - db::Instance child_inst = pi->child_inst (); - - connected_clusters &parent_cc = clusters_per_cell (pi->parent_cell_index ()); - for (db::CellInstArray::iterator pii = child_inst.begin (); ! pii.at_end (); ++pii) { - - ClusterInstance ci2 (id, child_inst.cell_index (), child_inst.complex_trans (*pii), child_inst.prop_id ()); - if (seen.find (std::make_pair (pi->parent_cell_index (), ci2)) == seen.end ()) { - - size_t id_dummy; - - const typename db::local_cluster::global_nets &gn = child_cc.cluster_by_id (id).get_global_nets (); - if (gn.empty ()) { - id_dummy = parent_cc.insert_dummy (); - } else { - local_cluster *lc = parent_cc.insert (); - lc->set_global_nets (gn); - id_dummy = lc->id (); - } - - parent_cc.add_connection (id_dummy, ci2); - seen.insert (std::make_pair (pi->parent_cell_index (), ci2)); - - if (pci == pi->parent_cell_index () && ci == ci2) { - id_new = id_dummy; - } - - } - - } - - } - - child_cc.reset_root (id); - - } - - // no parent -> create vertical connector - id = id_new; - tl_assert (id != 0); - - } - - } -} - template void hier_clusters::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, const tl::equivalence_clusters *attr_equivalence, const std::set *breakout_cells) @@ -2562,27 +2193,26 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c // NOTE: don't use the gc pointer - it may become invalid during make_path (will also do a local.insert) size_t gcid = gc->id (); - for (std::set::const_iterator ci = ge->second.begin (); ci != ge->second.end (); ++ci) { + for (std::set::const_iterator i = ge->second.begin (); i != ge->second.end (); ++i) { - if (! ci->has_instance ()) { + if (! i->has_instance ()) { - local.join_cluster_with (gcid, ci->id ()); - local.remove_cluster (ci->id ()); + local.join_cluster_with (gcid, i->id ()); + local.remove_cluster (i->id ()); } else { - std::vector p; - p.push_back (*ci); - ClusterInstance k = make_path (layout, cell, ci->id (), p); + // ensures the cluster is propagated so we can connect it with another + propagate_cluster_inst (layout, cell, *i, cell.cell_index (), false); - size_t other_id = local.find_cluster_with_connection (k); + size_t other_id = local.find_cluster_with_connection (*i); if (other_id == gcid) { // shouldn't happen, but duplicate instances may trigger this } else if (other_id) { local.join_cluster_with (gcid, other_id); local.remove_cluster (other_id); } else { - local.add_connection (gcid, k); + local.add_connection (gcid, *i); } } diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index 0f1619aaf..a29dfcce3 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -769,7 +769,6 @@ struct InstanceToInstanceInteraction bool operator== (const InstanceToInstanceInteraction &other) const { - static const db::array_base_ptr_cmp_f arr_less; return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21) && equal_array_delegates (array1, other.array1) && equal_array_delegates (array2, other.array2); @@ -799,7 +798,7 @@ struct InstanceToInstanceInteraction db::ICplxTrans t21; }; -typedef std::map > instance_interaction_cache_type; +typedef std::map instance_interaction_cache_type; template class hier_clusters; template class connected_clusters; @@ -974,7 +973,7 @@ class DB_PUBLIC_TEMPLATE hier_clusters { public: typedef typename local_cluster::box_type box_type; - typedef std::map > instance_interaction_cache_type; + typedef std::map instance_interaction_cache_type; /** * @brief Creates an empty set of clusters @@ -1022,15 +1021,12 @@ public: void clear (); /** - * @brief Makes a valid path to a child cluster + * @brief Ensures a cluster instance is connected from all parents of the instantiated cell * - * Cluster connections can only cross one level of hierarchy. This method - * creates necessary dummy entries for the given path. + * If "with_self" is true, the specified instance "ci" is included in the connections. Otherwise + * there is not connection made for this instance. */ - ClusterInstance make_path (const db::Layout &layout, const db::Cell &cell, size_t id, const std::vector &path); - - // @@@ - size_t propagate_cluster_inst (const db::Layout &layout, const Cell &cell, const ClusterInstance &ci, db::cell_index_type pci, bool with_self); + size_t propagate_cluster_inst (const db::Layout &layout, const Cell &cell, const ClusterInstance &ci, db::cell_index_type parent_ci, bool with_self); private: void build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters *attr_equivalence); diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 7dcebd9d7..44f1eac29 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -159,8 +159,9 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo // Make sure we create one subcircuit for each instance of cells which do have circuits // associated. for (db::Cell::const_iterator inst = cell.begin (); ! inst.at_end (); ++inst) { - // @@@ ARRAY EXPANSION!!! - make_subcircuit (circuit, inst->cell_index (), inst->complex_trans (), subcircuits, circuits); + for (db::CellInstArray::iterator ii = inst->begin (); ! ii.at_end (); ++ii) { + make_subcircuit (circuit, inst->cell_index (), inst->complex_trans (*ii), subcircuits, circuits); + } } }