From 3011e77439ee5e98090995fb1fbfec23551d7fdd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 17 Mar 2024 20:42:30 +0100 Subject: [PATCH] Need to differentiate between non-connected pins and pins with up+down connection - introducing a pin direction mode --- src/db/db/dbLayoutToNetlistSoftConnections.cc | 49 +++++----- src/db/db/dbLayoutToNetlistSoftConnections.h | 90 +++++++++++++++++-- 2 files changed, 107 insertions(+), 32 deletions(-) diff --git a/src/db/db/dbLayoutToNetlistSoftConnections.cc b/src/db/db/dbLayoutToNetlistSoftConnections.cc index 7c3a071f9..3ecaf4995 100644 --- a/src/db/db/dbLayoutToNetlistSoftConnections.cc +++ b/src/db/db/dbLayoutToNetlistSoftConnections.cc @@ -39,14 +39,14 @@ SoftConnectionClusterInfo::SoftConnectionClusterInfo () // .. nothing yet .. } -void SoftConnectionClusterInfo::add (const db::Net *net, int dir, const db::Pin *pin, size_t partial_net_count) +void SoftConnectionClusterInfo::add (const db::Net *net, SoftConnectionPinDir dir, const db::Pin *pin, size_t partial_net_count) { // limiting the partial net count to 1 means we report errors only once in the // hierarchy, not on every level m_partial_net_count += std::min (size_t (1), partial_net_count); // this is where we make the decision about the partial nets ... - if (! pin && dir < 0) { + if (! pin && dir == SoftConnectionPinDir::down ()) { m_partial_net_count += 1; } @@ -72,21 +72,21 @@ SoftConnectionClusterInfo &SoftConnectionCircuitInfo::make_cluster () return m_cluster_info.back (); } -void SoftConnectionCircuitInfo::add_pin_info (const db::Pin *pin, int dir, SoftConnectionClusterInfo *sc_cluster_info) +void SoftConnectionCircuitInfo::add_pin_info (const db::Pin *pin, SoftConnectionPinDir dir, SoftConnectionClusterInfo *sc_cluster_info) { if (pin) { m_pin_info.insert (std::make_pair (pin->id (), std::make_pair (dir, sc_cluster_info))); } } -int SoftConnectionCircuitInfo::direction_per_pin (const db::Pin *pin) const +SoftConnectionPinDir SoftConnectionCircuitInfo::direction_per_pin (const db::Pin *pin) const { if (! pin) { - return 0; + return SoftConnectionPinDir (); } auto p = m_pin_info.find (pin->id ()); - return p != m_pin_info.end () ? p->second.first : 0; + return p != m_pin_info.end () ? p->second.first : SoftConnectionPinDir (); } const SoftConnectionClusterInfo *SoftConnectionCircuitInfo::get_cluster_info_per_pin (const db::Pin *pin) const @@ -188,17 +188,21 @@ SoftConnectionInfo::representative_polygon (const db::Net *net, const db::Layout return db::DPolygon (bbox); } -void SoftConnectionInfo::report_partial_nets (const db::Circuit *circuit, const SoftConnectionClusterInfo &cluster_info, db::LayoutToNetlist &l2n, const std::string &path, const db::DCplxTrans &trans, const std::string &top_cell, int &index) +void SoftConnectionInfo::report_partial_nets (const db::Circuit *circuit, const SoftConnectionClusterInfo &cluster_info, db::LayoutToNetlist &l2n, const std::string &path, const db::DCplxTrans &trans, const std::string &top_cell, int &index, std::set &seen) { for (auto cc = cluster_info.begin_clusters (); cc != cluster_info.end_clusters (); ++cc) { const db::Net *net = circuit->net_by_cluster_id (cc->first); - if (cc->second < 0 && ! net->is_floating ()) { + if (! seen.insert (net).second) { + continue; + } - std::string msg = tl::sprintf (tl::to_string (tr ("Partial net #%d: %s - %s")), ++index, path, net->expanded_name ()); + if (cc->second == SoftConnectionPinDir::down () && ! net->is_floating () && net->begin_pins () == net->end_pins ()) { - db::LogEntryData entry (l2n.top_level_mode () ? db::Error : db::Warning, top_cell, msg); + std::string msg = tl::sprintf (tl::to_string (tr ("\tPartial net #%d: %s - %s")), ++index, path, net->expanded_name ()); + + db::LogEntryData entry (db::NoSeverity, top_cell, msg); entry.set_geometry (representative_polygon (net, l2n, trans * db::CplxTrans (l2n.internal_layout ()->dbu ()))); l2n.log_entry (entry); @@ -225,7 +229,7 @@ void SoftConnectionInfo::report_partial_nets (const db::Circuit *circuit, const std::string p = path; p += std::string ("/") + circuit_ref->name (); p += std::string ("[") + subcircuit->trans ().to_string (true /*short*/) + "]:" + subcircuit->expanded_name (); - report_partial_nets (circuit_ref, *scci, l2n, p, trans * subcircuit->trans (), top_cell, index); + report_partial_nets (circuit_ref, *scci, l2n, p, trans * subcircuit->trans (), top_cell, index, seen); } @@ -248,22 +252,19 @@ void SoftConnectionInfo::report (db::LayoutToNetlist &l2n) const SoftConnectionCircuitInfo &sc_info = scc->second; - bool first = true; for (auto sc = sc_info.begin (); sc != sc_info.end (); ++sc) { if (sc->partial_net_count () < 2) { continue; } - if (first) { - tl::info << "Circuit " << c->name () << ":"; - first = false; - } - - l2n.log_entry (db::LogEntryData (l2n.top_level_mode () ? db::Error : db::Warning, c->name (), tl::to_string (tr ("Net with incomplete wiring (soft-connected partial nets)")))); + db::LogEntryData log_entry (l2n.top_level_mode () ? db::Error : db::Warning, c->name (), tl::to_string (tr ("Net with incomplete wiring (soft-connected partial nets)"))); + log_entry.set_category_name ("soft-connection-check"); + l2n.log_entry (log_entry); int index = 0; - report_partial_nets (c.operator-> (), *sc, l2n, c->name (), db::DCplxTrans (), c->name (), index); + std::set seen; + report_partial_nets (c.operator-> (), *sc, l2n, c->name (), db::DCplxTrans (), c->name (), index, seen); } @@ -303,14 +304,14 @@ void SoftConnectionInfo::build_clusters_for_circuit (const db::Circuit *circuit, // the direction of a net is 0 for "no connections" or "both up and down" // and -1 for "down-only" connections and +1 for "up-only" connections: - int dir = 0; + SoftConnectionPinDir dir; // direct soft connections to other nets for (int up = 0; up < 2; ++up) { std::set next = up ? shape_clusters.upward_soft_connections (*cc) : shape_clusters.downward_soft_connections (*cc); if (! next.empty () || net_has_up_or_down_subcircuit_connections (net, up)) { - dir += up ? 1 : -1; + dir |= up ? SoftConnectionPinDir::up () : SoftConnectionPinDir::down (); } for (auto i = next.begin (); i != next.end (); ++i) { if (seen.insert (*i).second) { @@ -362,15 +363,15 @@ void SoftConnectionInfo::build_clusters_for_circuit (const db::Circuit *circuit, bool SoftConnectionInfo::net_has_up_or_down_subcircuit_connections (const db::Net *net, bool up) { - int look_for_dir = up ? 1 : -1; + SoftConnectionPinDir look_for_dir = up ? SoftConnectionPinDir::up () : SoftConnectionPinDir::down (); for (auto sc = net->begin_subcircuit_pins (); sc != net->end_subcircuit_pins (); ++sc) { const db::Pin *pin = sc->pin (); const db::Circuit *ref = sc->subcircuit ()->circuit_ref (); auto scc_ref = m_scc_per_circuit.find (ref); if (scc_ref != m_scc_per_circuit.end ()) { - int dir = scc_ref->second.direction_per_pin (pin); - if (dir == look_for_dir) { + SoftConnectionPinDir dir = scc_ref->second.direction_per_pin (pin); + if (dir & look_for_dir) { return true; } } diff --git a/src/db/db/dbLayoutToNetlistSoftConnections.h b/src/db/db/dbLayoutToNetlistSoftConnections.h index 3ad5369a4..a13630465 100644 --- a/src/db/db/dbLayoutToNetlistSoftConnections.h +++ b/src/db/db/dbLayoutToNetlistSoftConnections.h @@ -46,6 +46,80 @@ template class hier_clusters; template class connected_clusters; class NetShape; +/** + * @brief A small struct representing a direction value for a pin + * + * The pin can be upward, downward connected, connected in both ways or not connected at all. + */ +class SoftConnectionPinDir +{ +public: + /** + * @brief Constructs from a single direction (+1: up, -1: down) + */ + explicit SoftConnectionPinDir (int dir = 0) + : m_flags (0) + { + if (dir > 0) { + m_flags = 1; + } else if (dir < 0) { + m_flags = 2; + } + } + + /** + * @brief Equality + */ + bool operator== (SoftConnectionPinDir other) const + { + return m_flags == other.m_flags; + } + + /** + * @brief Inequality + */ + bool operator!= (SoftConnectionPinDir other) const + { + return m_flags != other.m_flags; + } + + /** + * @brief Join two value + */ + SoftConnectionPinDir operator| (SoftConnectionPinDir other) const + { + SoftConnectionPinDir res = *this; + res.m_flags |= other.m_flags; + return res; + } + + SoftConnectionPinDir &operator|= (SoftConnectionPinDir other) + { + m_flags |= other.m_flags; + return *this; + } + + /** + * @brief Test for one direction + */ + bool operator& (SoftConnectionPinDir other) const + { + return (m_flags & other.m_flags) != 0; + } + + /** + * @brief Static getters for the constants + */ + + inline static SoftConnectionPinDir none () { return SoftConnectionPinDir (0); } + inline static SoftConnectionPinDir up () { return SoftConnectionPinDir (1); } + inline static SoftConnectionPinDir down () { return SoftConnectionPinDir (-1); } + inline static SoftConnectionPinDir both () { return up () | down (); } + +private: + unsigned int m_flags; +}; + /** * @brief Describes a soft-connected cluster * @@ -58,7 +132,7 @@ class DB_PUBLIC SoftConnectionClusterInfo public: typedef std::set pin_set; typedef pin_set::const_iterator pin_iterator; - typedef std::map dir_map; + typedef std::map dir_map; typedef dir_map::const_iterator dir_map_iterator; SoftConnectionClusterInfo (); @@ -67,11 +141,11 @@ public: * @brief Enters information about a specific net * * @param net The Net for which we are entering information - * @param dir The direction code of the net (0: no soft connection or both directions, +1: up-only, -1: down-only) + * @param dir The direction code of the net * @param pin A pin that might leading outside our current circuit from this net (0 if there is none) * @param partial_net_count The partial net count of nets attached to this net inside subcircuits */ - void add (const db::Net *net, int dir, const db::Pin *pin, size_t partial_net_count); + void add (const db::Net *net, SoftConnectionPinDir dir, const db::Pin *pin, size_t partial_net_count); /** * @brief Gets the partial net count @@ -163,15 +237,15 @@ public: * @brief Adds information about a pin * * @param pin The pin - * @param dir The nature of connections from the pin: 0 if no soft connections / both directions, +1 to "up only" and -1 for "down only" + * @param dir The direction of connections from the pin * @param sc_cluster_info The soft-connected net cluster info object */ - void add_pin_info (const db::Pin *pin, int dir, SoftConnectionClusterInfo *sc_cluster_info); + void add_pin_info (const db::Pin *pin, SoftConnectionPinDir dir, SoftConnectionClusterInfo *sc_cluster_info); /** * @brief Gets the direction attribute of the pin */ - int direction_per_pin (const db::Pin *pin) const; + SoftConnectionPinDir direction_per_pin (const db::Pin *pin) const; /** * @brief Gets the soft-connected net cluster info object the pin connects to @@ -197,7 +271,7 @@ public: private: const db::Circuit *mp_circuit; cluster_list m_cluster_info; - std::map > m_pin_info; + std::map > m_pin_info; }; /** @@ -266,7 +340,7 @@ private: */ std::set net_connections_through_subcircuits (const db::Net *net, size_t &partial_net_count); - void report_partial_nets (const db::Circuit *circuit, const SoftConnectionClusterInfo &cluster_info, LayoutToNetlist &l2n, const std::string &path, const db::DCplxTrans &trans, const std::string &top_cell, int &index); + void report_partial_nets (const db::Circuit *circuit, const SoftConnectionClusterInfo &cluster_info, LayoutToNetlist &l2n, const std::string &path, const db::DCplxTrans &trans, const std::string &top_cell, int &index, std::set &seen); db::DPolygon representative_polygon (const db::Net *net, const db::LayoutToNetlist &l2n, const db::CplxTrans &trans); };