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 ..
}
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<const db::Net *> &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<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"
// 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<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)) {
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;
}
}

View File

@ -46,6 +46,80 @@ template <class T> class hier_clusters;
template <class T> 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<size_t> pin_set;
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;
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<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);
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);
};