diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index a8862ef39..dccedd970 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -227,6 +227,13 @@ local_cluster::clear () m_attrs.clear (); } +template +void +local_cluster::set_global_nets (const global_nets &gn) +{ + m_global_nets = gn; +} + template void local_cluster::add_attr (attr_id a) @@ -667,6 +674,9 @@ struct cluster_building_receiver { typedef typename local_cluster::id_type id_type; typedef std::pair > shape_value; + typedef std::vector shape_vector; + typedef std::set global_nets; + typedef std::pair cluster_value; cluster_building_receiver (const db::Connectivity &conn) : mp_conn (&conn) @@ -677,15 +687,17 @@ struct cluster_building_receiver void generate_clusters (local_clusters &clusters) { // build the resulting clusters - for (typename std::list >::const_iterator c = m_clusters.begin (); c != m_clusters.end (); ++c) { + for (typename std::list::const_iterator c = m_clusters.begin (); c != m_clusters.end (); ++c) { // TODO: reserve? local_cluster *cluster = clusters.insert (); - for (typename std::vector::const_iterator s = c->begin (); s != c->end (); ++s) { + for (typename shape_vector::const_iterator s = c->first.begin (); s != c->first.end (); ++s) { cluster->add (*s->first, s->second.first); cluster->add_attr (s->second.second); } + cluster->set_global_nets (c->second); + } } @@ -695,69 +707,106 @@ struct cluster_building_receiver return; } - typename std::map >::iterator>::iterator ic1 = m_shape_to_clusters.find (s1); - typename std::map >::iterator>::iterator ic2 = m_shape_to_clusters.find (s2); + typename std::map::iterator>::iterator ic1 = m_shape_to_clusters.find (s1); + typename std::map::iterator>::iterator ic2 = m_shape_to_clusters.find (s2); if (ic1 == m_shape_to_clusters.end ()) { if (ic2 == m_shape_to_clusters.end ()) { - m_clusters.push_back (std::vector ()); - typename std::list >::iterator c = --m_clusters.end (); - c->push_back (std::make_pair (s1, p1)); - c->push_back (std::make_pair (s2, p2)); + m_clusters.push_back (cluster_value ()); + typename std::list::iterator c = --m_clusters.end (); + c->first.push_back (std::make_pair (s1, p1)); + c->first.push_back (std::make_pair (s2, p2)); m_shape_to_clusters.insert (std::make_pair (s1, c)); m_shape_to_clusters.insert (std::make_pair (s2, c)); } else { - ic2->second->push_back (std::make_pair (s1, p1)); + ic2->second->first.push_back (std::make_pair (s1, p1)); m_shape_to_clusters.insert (std::make_pair (s1, ic2->second)); } } else if (ic2 == m_shape_to_clusters.end ()) { - ic1->second->push_back (std::make_pair (s2, p2)); + ic1->second->first.push_back (std::make_pair (s2, p2)); m_shape_to_clusters.insert (std::make_pair (s2, ic1->second)); } else if (ic1->second != ic2->second) { // join clusters: use the larger one as the target - if (ic1->second->size () < ic2->second->size ()) { - std::swap (ic1, ic2); + if (ic1->second->first.size () < ic2->second->first.size ()) { + join (ic2->second, ic1->second); + } else { + join (ic1->second, ic2->second); } - ic1->second->insert (ic1->second->end (), ic2->second->begin (), ic2->second->end ()); - - typename std::list >::iterator j = ic2->second; - for (typename std::vector::const_iterator i = j->begin (); i != j->end (); ++i) { - m_shape_to_clusters [i->first] = ic1->second; - } - - m_clusters.erase (j); - } } void finish (const T *s, std::pair p) { // if the shape has not been handled yet, insert a single cluster with only this shape - typename std::map >::iterator>::const_iterator ic = m_shape_to_clusters.find (s); + typename std::map::iterator>::iterator ic = m_shape_to_clusters.find (s); if (ic == m_shape_to_clusters.end ()) { - m_clusters.push_back (std::vector ()); - typename std::list >::iterator c = --m_clusters.end (); - c->push_back (std::make_pair (s, p)); - m_shape_to_clusters.insert (std::make_pair (s, c)); + + m_clusters.push_back (cluster_value ()); + typename std::list::iterator c = --m_clusters.end (); + c->first.push_back (std::make_pair (s, p)); + + ic = m_shape_to_clusters.insert (std::make_pair (s, c)).first; + + } + + // consider connections to global nets + + db::Connectivity::global_nets_iterator ge = mp_conn->end_global_connections (p.first); + for (db::Connectivity::global_nets_iterator g = mp_conn->begin_global_connections (p.first); g != ge; ++g) { + + typename std::map::iterator>::iterator icg = m_global_to_clusters.find (*g); + + if (icg == m_global_to_clusters.end ()) { + + ic->second->second.insert (*g); + m_global_to_clusters.insert (std::make_pair (*g, ic->second)); + + } else if (ic->second != icg->second) { + + // join clusters + if (ic->second->first.size () < icg->second->first.size ()) { + join (icg->second, ic->second); + } else { + join (ic->second, icg->second); + } + + } + } } private: const db::Connectivity *mp_conn; - std::map >::iterator> m_shape_to_clusters; - std::list > m_clusters; + std::map::iterator> m_shape_to_clusters; + std::map::iterator> m_global_to_clusters; + std::list m_clusters; + + void join (typename std::list::iterator ic1, typename std::list::iterator ic2) + { + ic1->first.insert (ic1->first.end (), ic2->first.begin (), ic2->first.end ()); + ic1->second.insert (ic2->second.begin (), ic2->second.end ()); + + for (typename shape_vector::const_iterator i = ic2->first.begin (); i != ic2->first.end (); ++i) { + m_shape_to_clusters [i->first] = ic1; + } + for (typename global_nets::const_iterator i = ic2->second.begin (); i != ic2->second.end (); ++i) { + m_global_to_clusters [*i] = ic1; + } + + m_clusters.erase (ic2); + } }; } diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index ca551c731..e1bfe3746 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -171,6 +171,9 @@ public: typedef size_t attr_id; typedef std::set attr_set; typedef attr_set::const_iterator attr_iterator; + typedef size_t global_net_id; + typedef std::set global_nets; + typedef global_nets::const_iterator global_nets_iterator; /** * @brief Creates an empty cluster @@ -287,6 +290,27 @@ public: return m_attrs.end (); } + /** + * @brief Gets the global net IDs (begin) + */ + global_nets_iterator begin_global_nets () const + { + return m_global_nets.begin (); + } + + /** + * @brief Gets the global net IDs (end) + */ + global_nets_iterator end_global_nets () const + { + return m_global_nets.end (); + } + + /** + * @brief Sets the global nets + */ + void set_global_nets (const global_nets &gn); + private: template friend class local_clusters; template friend class interaction_receiver; @@ -310,6 +334,7 @@ private: std::map m_shapes; box_type m_bbox; attr_set m_attrs; + global_nets m_global_nets; size_t m_size; }; diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 02fcdaa0f..7fe733bbf 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -100,13 +100,11 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect net->set_cluster_id (*c); circuit->add_net (net); - // make global net connections for clusters which connect to such - std::set global_net_ids; - std::vector layers = clusters.cluster_by_id (*c).layers (); - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { - global_net_ids.insert (conn.begin_global_connections (*l), conn.end_global_connections (*l)); - } - for (std::set::const_iterator g = global_net_ids.begin (); g != global_net_ids.end (); ++g) { + const db::local_cluster &cluster = clusters.cluster_by_id (*c); + + // collect global net assignments from clusters + for (std::set::const_iterator g = cluster.begin_global_nets (); g != cluster.end_global_nets (); ++g) { + tl_assert (global_nets.find (*g) == global_nets.end ()); global_nets.insert (std::make_pair (*g, net)); assign_net_name (conn.global_net_name (*g), net); } @@ -153,6 +151,30 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect } + // if any of the subcircuits has global nets which this circuit doesn't have, propagate them + + std::set seen; + std::set global_nets_of_subcircuits; + for (db::Circuit::subcircuit_iterator sc = circuit->begin_subcircuits (); sc != circuit->end_subcircuits (); ++sc) { + + db::Circuit *subcircuit = sc->circuit_ref (); + if (seen.find (subcircuit) == seen.end ()) { + + seen.insert (subcircuit); + + const std::map &sc_gn = global_nets_per_cell [subcircuit->cell_index ()]; + for (std::map::const_iterator g = sc_gn.begin (); g != sc_gn.end (); ++g) { + global_nets_of_subcircuits.insert (g->first); + } + + } + + } + + for (std::set::const_iterator g = global_nets_of_subcircuits.begin (); g != global_nets_of_subcircuits.end (); ++g) { + + } + // make the global net connections into subcircuits - if necessary by creating pins into the subcircuit for (db::Circuit::subcircuit_iterator sc = circuit->begin_subcircuits (); sc != circuit->end_subcircuits (); ++sc) { diff --git a/src/db/unit_tests/dbHierNetworkProcessorTests.cc b/src/db/unit_tests/dbHierNetworkProcessorTests.cc index 96c7d7563..8890780a6 100644 --- a/src/db/unit_tests/dbHierNetworkProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetworkProcessorTests.cc @@ -292,6 +292,9 @@ static std::string local_cluster_to_string (const db::local_cluster &cluster, for (typename db::local_cluster::attr_iterator a = cluster.begin_attr (); a != cluster.end_attr (); ++a) { res += "%" + tl::to_string (*a); } + for (typename db::local_cluster::global_nets_iterator g = cluster.begin_global_nets (); g != cluster.end_global_nets (); ++g) { + res += "+" + conn.global_net_name (*g); + } return res; } @@ -462,6 +465,75 @@ TEST(21_LocalClustersBasicWithAttributes) ); } +TEST(22_LocalClustersWithGlobal) +{ + db::Layout layout; + db::Cell &cell = layout.cell (layout.add_cell ("TOP")); + db::GenericRepository &repo = layout.shape_repository (); + + db::Connectivity conn; + conn.connect (0); + conn.connect (1); + conn.connect (2); + conn.connect (0, 1); + conn.connect (0, 2); + + db::Polygon poly; + tl::from_string ("(0,0;0,1000;1000,1000;1000,0)", poly); + + cell.shapes (0).insert (db::PolygonRef (poly, repo)); + + db::local_clusters clusters; + EXPECT_EQ (local_clusters_to_string (clusters, conn), ""); + + clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0)"); + + // one more shape + cell.shapes (0).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (10, 20))), repo), 1)); + + clusters.clear (); + clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + EXPECT_EQ (local_clusters_to_string (clusters, conn), "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1"); + + // one more shape creating a new cluster + cell.shapes (2).insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (db::Trans (db::Vector (0, 1100))), repo), 2)); + + clusters.clear (); + clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + EXPECT_EQ (local_clusters_to_string (clusters, conn), + "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1\n" + "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2" + ); + + conn.connect_global (0, "GLOBAL"); + + clusters.clear (); + clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + EXPECT_EQ (local_clusters_to_string (clusters, conn), + "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1+GLOBAL\n" + "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2" + ); + + conn.connect_global (2, "GLOBAL2"); + + clusters.clear (); + clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + EXPECT_EQ (local_clusters_to_string (clusters, conn), + "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20)%1+GLOBAL\n" + "#2:[2](0,1100;0,2100;1000,2100;1000,1100)%2+GLOBAL2" + ); + + conn.connect_global (0, "GLOBAL2"); + + // now, GLOBAL2 will connect these clusters + clusters.clear (); + clusters.build_clusters (cell, db::ShapeIterator::Polygons, conn); + EXPECT_EQ (local_clusters_to_string (clusters, conn), + "#1:[0](0,0;0,1000;1000,1000;1000,0);[0](10,20;10,1020;1010,1020;1010,20);[2](0,1100;0,2100;1000,2100;1000,1100)%1%2+GLOBAL+GLOBAL2" + ); +} + TEST(30_LocalConnectedClusters) { db::Layout layout;