diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 7f2acce95..d8ed3d9a9 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -524,8 +524,8 @@ class DB_PUBLIC hnp_interaction_receiver public: typedef typename local_cluster::box_type box_type; - hnp_interaction_receiver (const Connectivity &conn, const db::ICplxTrans &trans) - : mp_conn (&conn), m_any (false), m_soft_mode (0), m_trans (trans) + hnp_interaction_receiver (const Connectivity &conn, const db::ICplxTrans &trans, std::map > *interacting_this, std::map > *interacting_other) + : mp_conn (&conn), m_any (false), m_soft_mode (0), m_trans (trans), mp_interacting_this (interacting_this), mp_interacting_other (interacting_other) { // .. nothing yet .. } @@ -534,9 +534,17 @@ public: { int soft = 0; if (mp_conn->interacts (*s1, l1, *s2, l2, m_trans, soft)) { + if (mp_interacting_this) { + (*mp_interacting_this) [l1].insert (s1); + } + if (mp_interacting_other) { + (*mp_interacting_this) [l2].insert (s2); + } if (soft == 0 || (m_soft_mode != 0 && m_soft_mode != soft)) { m_soft_mode = 0; - m_any = true; + if (! mp_interacting_other && ! mp_interacting_this) { + m_any = true; + } } else { m_soft_mode = soft; } @@ -558,6 +566,7 @@ private: bool m_any; int m_soft_mode; db::ICplxTrans m_trans; + std::map > *mp_interacting_this, *mp_interacting_other; }; template @@ -619,9 +628,31 @@ local_cluster::interacts (const db::Cell &cell, const db::ICplxTrans &trans, return false; } +template +static +void collect_interactions_in_original_order (const std::map::tree_type> &shapes, const std::map > &interacting, std::map > &interacting_out) +{ + for (typename std::map >::const_iterator i = interacting.begin (); i != interacting.end (); ++i) { + + std::vector &t = interacting_out [i->first]; + auto s = shapes.find (i->first); + if (s == shapes.end ()) { + continue; + } + + t.reserve (t.size () + i->second.size ()); + for (auto j = s->second.begin (); j != s->second.end (); ++j) { + if (i->second.find (j.operator-> ()) != i->second.end ()) { + t.push_back (j.operator-> ()); + } + } + + } +} + template bool -local_cluster::interacts (const local_cluster &other, const db::ICplxTrans &trans, const Connectivity &conn, int &soft) const +local_cluster::interacts (const local_cluster &other, const db::ICplxTrans &trans, const Connectivity &conn, int &soft, std::map > *interacting_this, std::map > *interacting_other) const { db::box_convert bc; @@ -679,11 +710,25 @@ local_cluster::interacts (const local_cluster &other, const db::ICplxTrans } } - hnp_interaction_receiver rec (conn, trans); + std::map > is_this, is_other; + std::map > *p_is_this = interacting_this ? &is_this : 0; + std::map > *p_is_other = interacting_other ? &is_other : 0; + + hnp_interaction_receiver rec (conn, trans, p_is_this, p_is_other); if (! scanner.process (rec, 1 /*==touching*/, bc, bc_t) || rec.soft_mode () != 0) { + + if (p_is_this) { + collect_interactions_in_original_order (m_shapes, *p_is_this, *interacting_this); + } + if (p_is_other) { + collect_interactions_in_original_order (other.m_shapes, *p_is_other, *interacting_other); + } + soft = rec.soft_mode (); + return true; + } else { return false; } diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index ad97c7fad..d035075a1 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -326,8 +326,10 @@ public: * * "trans" is the transformation which is applied to the other cluster before * the test. + * If non-null "interacting_this" will receive all interacting shapes from *this in case of success. + * If non-null "interacting_other" will receive all interacting shapes from other in case of success. */ - bool interacts (const local_cluster &other, const db::ICplxTrans &trans, const Connectivity &conn, int &soft) const; + bool interacts (const local_cluster &other, const db::ICplxTrans &trans, const Connectivity &conn, int &soft, std::map > *interacting_this = 0, std::map > *interacting_other = 0) const; /** * @brief Tests whether this cluster interacts with the given cell diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 86b7d50ab..e503518f9 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -1308,6 +1308,14 @@ static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const return true; } +std::map +LayoutToNetlist::shapes_of_pin (const db::NetSubcircuitPinRef &pin, const db::ICplxTrans &trans) const +{ + + // @@@ + +} + void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid, const ICplxTrans &trans) const { unsigned int lid = layer_of (of_layer); diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index e8c78d217..f1b426392 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -828,6 +828,19 @@ public: return m_net_clusters; } + /** + * @brief Gets the shapes that make the subcircuit pin + * + * This method looks up all shapes from the subcircuit that interact with the shapes of the net + * the subcircuit pin lives in. It will return a map of layer index vs. Region with these + * shapes, transformed into the coordinate space of the net. + * + * Note that this method only considers top-down interactions between the shapes of the net + * and subcircuits, not between subcircuits. It is useful only for certain topologies - i.e. + * digital nets connecting gate cells. + */ + std::map shapes_of_pin (const db::NetSubcircuitPinRef &pin, const db::ICplxTrans &trans = db::ICplxTrans ()) const; + /** * @brief Returns all shapes of a specific net and layer. * diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index e041f5ae9..26b670fc5 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -678,6 +678,22 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method ("netlist", &db::LayoutToNetlist::netlist, "@brief gets the netlist extracted (0 if no extraction happened yet)\n" ) + + gsi::method ("shapes_of_pin", &db::LayoutToNetlist::shapes_of_pin, gsi::arg ("pin"), gsi::arg ("trans", db::ICplxTrans (), "unity"), + "@brief Returns all shapes of the given subcircuit pin.\n" + "This will return all shapes from the subcircuit attached by the given pin that interact with the net.\n" + "This method returns a \Region object with the shapes per layer where interactions are found.\n" + "The layers are given as layer indexes.\n" + "\n" + "The returned shapes are already transformed into the coordinate system of the net (see \\shapes_of_net for example).\n" + "An additional transformation can be applied using the optional \\trans argument.\n" + "\n" + "Note, that this method only considers interations between net shapes and subcircuits, not between subcircuits.\n" + "It can be used for example for digital nets connecting gate cells. In the general case however, nets may be formed\n" + "also by touching subcircuits. In that case, the nets do not have shapes of their own and this function cannot detect\n" + "the pin shapes.\n" + "\n" + "This method has been introduced in version 0.29.2." + ) + gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, const db::ICplxTrans &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive", true), gsi::arg ("trans", db::ICplxTrans (), "unity"), "@brief Returns all shapes of a specific net and layer.\n" "If 'recursive'' is true, the returned region will contain the shapes of\n"