Need to differentiate between non-connected pins and pins with up+down connection - introducing a pin direction mode

This commit is contained in:
Matthias Koefferlein 2024-03-17 20:42:30 +01:00
parent 203a62f0af
commit 3011e77439
2 changed files with 107 additions and 32 deletions

View File

@ -39,14 +39,14 @@ SoftConnectionClusterInfo::SoftConnectionClusterInfo ()
// .. nothing yet .. // .. 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 // limiting the partial net count to 1 means we report errors only once in the
// hierarchy, not on every level // hierarchy, not on every level
m_partial_net_count += std::min (size_t (1), partial_net_count); m_partial_net_count += std::min (size_t (1), partial_net_count);
// this is where we make the decision about the partial nets ... // 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; m_partial_net_count += 1;
} }
@ -72,21 +72,21 @@ SoftConnectionClusterInfo &SoftConnectionCircuitInfo::make_cluster ()
return m_cluster_info.back (); 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) { if (pin) {
m_pin_info.insert (std::make_pair (pin->id (), std::make_pair (dir, sc_cluster_info))); 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) { if (! pin) {
return 0; return SoftConnectionPinDir ();
} }
auto p = m_pin_info.find (pin->id ()); 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 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); 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<const db::Net *> &seen)
{ {
for (auto cc = cluster_info.begin_clusters (); cc != cluster_info.end_clusters (); ++cc) { for (auto cc = cluster_info.begin_clusters (); cc != cluster_info.end_clusters (); ++cc) {
const db::Net *net = circuit->net_by_cluster_id (cc->first); 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 ()))); entry.set_geometry (representative_polygon (net, l2n, trans * db::CplxTrans (l2n.internal_layout ()->dbu ())));
l2n.log_entry (entry); l2n.log_entry (entry);
@ -225,7 +229,7 @@ void SoftConnectionInfo::report_partial_nets (const db::Circuit *circuit, const
std::string p = path; std::string p = path;
p += std::string ("/") + circuit_ref->name (); p += std::string ("/") + circuit_ref->name ();
p += std::string ("[") + subcircuit->trans ().to_string (true /*short*/) + "]:" + subcircuit->expanded_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; const SoftConnectionCircuitInfo &sc_info = scc->second;
bool first = true;
for (auto sc = sc_info.begin (); sc != sc_info.end (); ++sc) { for (auto sc = sc_info.begin (); sc != sc_info.end (); ++sc) {
if (sc->partial_net_count () < 2) { if (sc->partial_net_count () < 2) {
continue; continue;
} }
if (first) { 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)")));
tl::info << "Circuit " << c->name () << ":"; log_entry.set_category_name ("soft-connection-check");
first = false; l2n.log_entry (log_entry);
}
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; int index = 0;
report_partial_nets (c.operator-> (), *sc, l2n, c->name (), db::DCplxTrans (), c->name (), index); std::set<const db::Net *> 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" // 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: // and -1 for "down-only" connections and +1 for "up-only" connections:
int dir = 0; SoftConnectionPinDir dir;
// direct soft connections to other nets // direct soft connections to other nets
for (int up = 0; up < 2; ++up) { for (int up = 0; up < 2; ++up) {
std::set<size_t> next = up ? shape_clusters.upward_soft_connections (*cc) : shape_clusters.downward_soft_connections (*cc); std::set<size_t> 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)) { 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) { for (auto i = next.begin (); i != next.end (); ++i) {
if (seen.insert (*i).second) { 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) 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) { for (auto sc = net->begin_subcircuit_pins (); sc != net->end_subcircuit_pins (); ++sc) {
const db::Pin *pin = sc->pin (); const db::Pin *pin = sc->pin ();
const db::Circuit *ref = sc->subcircuit ()->circuit_ref (); const db::Circuit *ref = sc->subcircuit ()->circuit_ref ();
auto scc_ref = m_scc_per_circuit.find (ref); auto scc_ref = m_scc_per_circuit.find (ref);
if (scc_ref != m_scc_per_circuit.end ()) { if (scc_ref != m_scc_per_circuit.end ()) {
int dir = scc_ref->second.direction_per_pin (pin); SoftConnectionPinDir dir = scc_ref->second.direction_per_pin (pin);
if (dir == look_for_dir) { if (dir & look_for_dir) {
return true; return true;
} }
} }

View File

@ -46,6 +46,80 @@ template <class T> class hier_clusters;
template <class T> class connected_clusters; template <class T> class connected_clusters;
class NetShape; 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 * @brief Describes a soft-connected cluster
* *
@ -58,7 +132,7 @@ class DB_PUBLIC SoftConnectionClusterInfo
public: public:
typedef std::set<size_t> pin_set; typedef std::set<size_t> pin_set;
typedef pin_set::const_iterator pin_iterator; typedef pin_set::const_iterator pin_iterator;
typedef std::map<size_t, int> dir_map; typedef std::map<size_t, SoftConnectionPinDir> dir_map;
typedef dir_map::const_iterator dir_map_iterator; typedef dir_map::const_iterator dir_map_iterator;
SoftConnectionClusterInfo (); SoftConnectionClusterInfo ();
@ -67,11 +141,11 @@ public:
* @brief Enters information about a specific net * @brief Enters information about a specific net
* *
* @param net The Net for which we are entering information * @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 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 * @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 * @brief Gets the partial net count
@ -163,15 +237,15 @@ public:
* @brief Adds information about a pin * @brief Adds information about a pin
* *
* @param pin The 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 * @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 * @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 * @brief Gets the soft-connected net cluster info object the pin connects to
@ -197,7 +271,7 @@ public:
private: private:
const db::Circuit *mp_circuit; const db::Circuit *mp_circuit;
cluster_list m_cluster_info; cluster_list m_cluster_info;
std::map<size_t, std::pair<int, const SoftConnectionClusterInfo *> > m_pin_info; std::map<size_t, std::pair<SoftConnectionPinDir, const SoftConnectionClusterInfo *> > m_pin_info;
}; };
/** /**
@ -266,7 +340,7 @@ private:
*/ */
std::set<size_t> net_connections_through_subcircuits (const db::Net *net, size_t &partial_net_count); std::set<size_t> 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<const Net *> &seen);
db::DPolygon representative_polygon (const db::Net *net, const db::LayoutToNetlist &l2n, const db::CplxTrans &trans); db::DPolygon representative_polygon (const db::Net *net, const db::LayoutToNetlist &l2n, const db::CplxTrans &trans);
}; };