mirror of https://github.com/KLayout/klayout.git
WIP: preparations for global net extraction
This commit is contained in:
parent
64c2548ab8
commit
6cf7558384
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue