From b10cda574cd88e7d1c97fa54b162efcfa510c6f5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 17 Mar 2024 17:39:39 +0100 Subject: [PATCH] Reporting --- src/db/db/dbLayoutToNetlist.cc | 34 +++----- src/db/db/dbLayoutToNetlistSoftConnections.cc | 85 +++++++++++++++++-- src/db/db/dbLayoutToNetlistSoftConnections.h | 10 ++- 3 files changed, 99 insertions(+), 30 deletions(-) diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 0b2ab5c55..74aa559cb 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -545,7 +545,7 @@ void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a check_must_connect_impl (c, a, b, c, a, b, path); } -static std::string path_msg (const std::vector &path, const db::Circuit &c_org) +static std::string path_msg (const std::vector &path) { if (path.empty ()) { return std::string (); @@ -553,15 +553,13 @@ static std::string path_msg (const std::vector &path, co std::string msg (".\n" + tl::to_string (tr ("Instance path: "))); - for (auto p = path.rbegin (); p != path.rend (); ++p) { - if (p != path.rbegin ()) { - msg += "/"; - } - msg += (*p)->circuit ()->name () + ":" + (*p)->expanded_name () + "[" + (*p)->trans ().to_string () + "]"; - } + auto p0 = path.rbegin (); + msg += (*p0)->circuit ()->name (); - msg += "/"; - msg += c_org.name (); + for (auto p = p0; p != path.rend (); ++p) { + msg += "/"; + msg += (*p)->circuit_ref ()->name () + "[" + (*p)->trans ().to_string (true /*short*/) + "]" + ":" + (*p)->expanded_name (); + } return msg; } @@ -587,12 +585,12 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N if (a_org.expanded_name () == b_org.expanded_name ()) { if (path.empty ()) { - db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name ()) + path_msg (path, c_org)); + db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name ()) + path_msg (path)); warn.set_cell_name (c.name ()); warn.set_category_name ("must-connect"); log_entry (warn); } else { - db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), c_org.name ()) + path_msg (path, c_org)); + db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), c_org.name ()) + path_msg (path)); warn.set_cell_name (c.name ()); warn.set_geometry (subcircuit_geometry (*path.back (), internal_layout ())); warn.set_category_name ("must-connect"); @@ -600,12 +598,12 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N } } else { if (path.empty ()) { - db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), b_org.expanded_name ()) + path_msg (path, c_org)); + db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), b_org.expanded_name ()) + path_msg (path)); warn.set_cell_name (c.name ()); warn.set_category_name ("must-connect"); log_entry (warn); } else { - db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), b_org.expanded_name (), c_org.name ()) + path_msg (path, c_org)); + db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), a_org.expanded_name (), b_org.expanded_name (), c_org.name ()) + path_msg (path)); warn.set_cell_name (c.name ()); warn.set_geometry (subcircuit_geometry (*path.back (), internal_layout ())); warn.set_category_name ("must-connect"); @@ -626,7 +624,7 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N const db::Net *net_b = sc.net_for_pin (b.begin_pins ()->pin_id ()); if (net_a == 0) { - db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s is not connected at all%s")), a_org.expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path, c_org)); + db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s is not connected at all%s")), a_org.expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path)); error.set_cell_name (sc.circuit ()->name ()); error.set_geometry (subcircuit_geometry (sc, internal_layout ())); error.set_category_name ("must-connect"); @@ -634,7 +632,7 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N } if (net_b == 0) { - db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s is not connected at all%s")), b_org.expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path, c_org)); + db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s is not connected at all%s")), b_org.expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path)); error.set_cell_name (sc.circuit ()->name ()); error.set_geometry (subcircuit_geometry (sc, internal_layout ())); error.set_category_name ("must-connect"); @@ -691,11 +689,7 @@ void LayoutToNetlist::do_soft_connections () { SoftConnectionInfo sc_info; sc_info.build (*netlist (), net_clusters ()); - - // @@@ - sc_info.print_errors (*netlist ()); - // @@@ - + sc_info.report (*this); sc_info.join_soft_connections (*netlist ()); } diff --git a/src/db/db/dbLayoutToNetlistSoftConnections.cc b/src/db/db/dbLayoutToNetlistSoftConnections.cc index 0380d4dca..7c3a071f9 100644 --- a/src/db/db/dbLayoutToNetlistSoftConnections.cc +++ b/src/db/db/dbLayoutToNetlistSoftConnections.cc @@ -24,6 +24,7 @@ #include "dbCommon.h" #include "dbLayoutToNetlistSoftConnections.h" #include "dbLayoutToNetlist.h" +#include "dbHierNetworkProcessor.h" #include "dbNetlist.h" namespace db @@ -166,9 +167,79 @@ void SoftConnectionInfo::join_soft_connections (db::Netlist &netlist) m_scc_per_circuit.clear (); } -void SoftConnectionInfo::print_errors (const db::Netlist &netlist) +db::DPolygon +SoftConnectionInfo::representative_polygon (const db::Net *net, const db::LayoutToNetlist &l2n, const db::CplxTrans &trans) { - for (auto c = netlist.begin_bottom_up (); c != netlist.end_bottom_up (); ++c) { + const db::Connectivity &conn = l2n.connectivity (); + const db::hier_clusters &net_clusters = l2n.net_clusters (); + + db::DBox bbox; + + for (auto l = conn.begin_layers (); l != conn.end_layers (); ++l) { + db::recursive_cluster_shape_iterator si (net_clusters, *l, net->circuit ()->cell_index (), net->cluster_id ()); + while (! si.at_end ()) { + if (si->type () == db::NetShape::Polygon) { + bbox += trans * (si.trans () * si->polygon_ref ().box ()); + } + ++si; + } + } + + 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) +{ + 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 ()) { + + std::string msg = tl::sprintf (tl::to_string (tr ("Partial net #%d: %s - %s")), ++index, path, net->expanded_name ()); + + db::LogEntryData entry (l2n.top_level_mode () ? db::Error : db::Warning, top_cell, msg); + entry.set_geometry (representative_polygon (net, l2n, trans * db::CplxTrans (l2n.internal_layout ()->dbu ()))); + + l2n.log_entry (entry); + + } + + for (auto sc = net->begin_subcircuit_pins (); sc != net->end_subcircuit_pins (); ++sc) { + + const db::SubCircuit *subcircuit = sc->subcircuit (); + const db::Circuit *circuit_ref = subcircuit->circuit_ref (); + + auto scc = m_scc_per_circuit.find (circuit_ref); + if (scc == m_scc_per_circuit.end ()) { + continue; + } + + const SoftConnectionCircuitInfo &sci = scc->second; + + const SoftConnectionClusterInfo *scci = sci.get_cluster_info_per_pin (sc->pin ()); + if (! scci || scci->partial_net_count () == 0) { + continue; + } + + 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); + + } + + } +} + +void SoftConnectionInfo::report (db::LayoutToNetlist &l2n) +{ + const db::Netlist *netlist = l2n.netlist (); + if (! netlist) { + return; + } + + for (auto c = netlist->begin_bottom_up (); c != netlist->end_bottom_up (); ++c) { auto scc = m_scc_per_circuit.find (c.operator-> ()); if (scc == m_scc_per_circuit.end ()) { @@ -189,12 +260,10 @@ void SoftConnectionInfo::print_errors (const db::Netlist &netlist) first = false; } - tl::info << " Partial nets on soft-connect cluster:"; - for (auto cc = sc->begin_clusters (); cc != sc->end_clusters (); ++cc) { - if (cc->second < 0) { - tl::info << " " << c->net_by_cluster_id (cc->first)->expanded_name (); - } - } + 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)")))); + + int index = 0; + report_partial_nets (c.operator-> (), *sc, l2n, c->name (), db::DCplxTrans (), c->name (), index); } diff --git a/src/db/db/dbLayoutToNetlistSoftConnections.h b/src/db/db/dbLayoutToNetlistSoftConnections.h index 9c2bad69d..3ad5369a4 100644 --- a/src/db/db/dbLayoutToNetlistSoftConnections.h +++ b/src/db/db/dbLayoutToNetlistSoftConnections.h @@ -24,11 +24,13 @@ #define _HDR_dbLayoutToNetlistSoftConnections #include "dbCommon.h" +#include "dbPolygon.h" #include #include #include #include +#include namespace db { @@ -38,6 +40,7 @@ class Pin; class Circuit; class Netlist; class SubCircuit; +class LayoutToNetlist; template class hier_clusters; template class connected_clusters; @@ -219,9 +222,9 @@ public: void join_soft_connections (db::Netlist &netlist); /** - * @brief For debugging + * @brief Create log entries */ - void print_errors (const db::Netlist &netlist); + void report (db::LayoutToNetlist &l2n); private: std::map m_scc_per_circuit; @@ -262,6 +265,9 @@ private: * The return value is a set of nets shape cluster IDs. */ 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); + db::DPolygon representative_polygon (const db::Net *net, const db::LayoutToNetlist &l2n, const db::CplxTrans &trans); }; }