WIP: preparations for global net extraction

This commit is contained in:
Matthias Koefferlein 2019-01-06 17:04:13 +01:00
parent 64c2548ab8
commit 6cf7558384
4 changed files with 203 additions and 35 deletions

View File

@ -227,6 +227,13 @@ local_cluster<T>::clear ()
m_attrs.clear ();
}
template <class T>
void
local_cluster<T>::set_global_nets (const global_nets &gn)
{
m_global_nets = gn;
}
template <class T>
void
local_cluster<T>::add_attr (attr_id a)
@ -667,6 +674,9 @@ struct cluster_building_receiver
{
typedef typename local_cluster<T>::id_type id_type;
typedef std::pair<const T *, std::pair<unsigned int, unsigned int> > shape_value;
typedef std::vector<shape_value> shape_vector;
typedef std::set<size_t> global_nets;
typedef std::pair<shape_vector, global_nets> 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<T> &clusters)
{
// build the resulting clusters
for (typename std::list<std::vector<shape_value> >::const_iterator c = m_clusters.begin (); c != m_clusters.end (); ++c) {
for (typename std::list<cluster_value>::const_iterator c = m_clusters.begin (); c != m_clusters.end (); ++c) {
// TODO: reserve?
local_cluster<T> *cluster = clusters.insert ();
for (typename std::vector<shape_value>::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<const T *, typename std::list<std::vector<shape_value> >::iterator>::iterator ic1 = m_shape_to_clusters.find (s1);
typename std::map<const T *, typename std::list<std::vector<shape_value> >::iterator>::iterator ic2 = m_shape_to_clusters.find (s2);
typename std::map<const T *, typename std::list<cluster_value>::iterator>::iterator ic1 = m_shape_to_clusters.find (s1);
typename std::map<const T *, typename std::list<cluster_value>::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<shape_value> ());
typename std::list<std::vector<shape_value> >::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<cluster_value>::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<std::vector<shape_value> >::iterator j = ic2->second;
for (typename std::vector<shape_value>::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<unsigned int, unsigned> p)
{
// if the shape has not been handled yet, insert a single cluster with only this shape
typename std::map<const T *, typename std::list<std::vector<shape_value> >::iterator>::const_iterator ic = m_shape_to_clusters.find (s);
typename std::map<const T *, typename std::list<cluster_value>::iterator>::iterator ic = m_shape_to_clusters.find (s);
if (ic == m_shape_to_clusters.end ()) {
m_clusters.push_back (std::vector<shape_value> ());
typename std::list<std::vector<shape_value> >::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<cluster_value>::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<size_t, typename std::list<cluster_value>::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<const T *, typename std::list<std::vector<shape_value> >::iterator> m_shape_to_clusters;
std::list<std::vector<shape_value> > m_clusters;
std::map<const T *, typename std::list<cluster_value>::iterator> m_shape_to_clusters;
std::map<size_t, typename std::list<cluster_value>::iterator> m_global_to_clusters;
std::list<cluster_value> m_clusters;
void join (typename std::list<cluster_value>::iterator ic1, typename std::list<cluster_value>::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);
}
};
}

View File

@ -171,6 +171,9 @@ public:
typedef size_t attr_id;
typedef std::set<attr_id> attr_set;
typedef attr_set::const_iterator attr_iterator;
typedef size_t global_net_id;
typedef std::set<global_net_id> 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 <typename> friend class local_clusters;
template <typename> friend class interaction_receiver;
@ -310,6 +334,7 @@ private:
std::map<unsigned int, tree_type> m_shapes;
box_type m_bbox;
attr_set m_attrs;
global_nets m_global_nets;
size_t m_size;
};

View File

@ -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<size_t> global_net_ids;
std::vector<unsigned int> layers = clusters.cluster_by_id (*c).layers ();
for (std::vector<unsigned int>::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<size_t>::const_iterator g = global_net_ids.begin (); g != global_net_ids.end (); ++g) {
const db::local_cluster<db::PolygonRef> &cluster = clusters.cluster_by_id (*c);
// collect global net assignments from clusters
for (std::set<size_t>::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<db::Circuit *> seen;
std::set<size_t> 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<size_t, db::Net *> &sc_gn = global_nets_per_cell [subcircuit->cell_index ()];
for (std::map<size_t, db::Net *>::const_iterator g = sc_gn.begin (); g != sc_gn.end (); ++g) {
global_nets_of_subcircuits.insert (g->first);
}
}
}
for (std::set<size_t>::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) {

View File

@ -292,6 +292,9 @@ static std::string local_cluster_to_string (const db::local_cluster<T> &cluster,
for (typename db::local_cluster<T>::attr_iterator a = cluster.begin_attr (); a != cluster.end_attr (); ++a) {
res += "%" + tl::to_string (*a);
}
for (typename db::local_cluster<T>::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<db::PolygonRef> 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;