Skip to content

Commit

Permalink
Merge pull request #1647 from KLayout/lvs-issues
Browse files Browse the repository at this point in the history
Lvs issues
  • Loading branch information
klayoutmatthias authored Mar 23, 2024
2 parents 206e271 + 2d91f7f commit 8f8a7d0
Show file tree
Hide file tree
Showing 18 changed files with 896 additions and 61 deletions.
101 changes: 73 additions & 28 deletions src/db/db/dbLayoutToNetlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -473,69 +473,114 @@ void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a
return;
}

if (c.begin_refs () != c.end_refs ()) {
std::vector<const db::SubCircuit *> path;
check_must_connect_impl (c, a, b, c, a, b, path);
}

static std::string path_msg (const std::vector<const db::SubCircuit *> &path, const db::Circuit &c_org)
{
if (path.empty ()) {
return std::string ();
}

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 () + "]";
}

msg += "/";
msg += c_org.name ();

return msg;
}

void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::Net &a, const db::Net &b, const db::Circuit &c_org, const db::Net &a_org, const db::Net &b_org, std::vector<const db::SubCircuit *> &path)
{
if (c.begin_refs () != c.end_refs () && path.empty ()) {

if (a.begin_pins () == a.end_pins ()) {
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a.expanded_name ()));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a_org.expanded_name ()));
error.set_cell_name (c.name ());
error.set_category_name ("must-connect");
log_entry (error);
}
if (b.begin_pins () == b.end_pins ()) {
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a.expanded_name ()));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a_org.expanded_name ()));
error.set_cell_name (c.name ());
error.set_category_name ("must-connect");
log_entry (error);
}
} else {
if (a.expanded_name () == b.expanded_name ()) {
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.expanded_name ()));
warn.set_cell_name (c.name ());
warn.set_category_name ("must-connect");
log_entry (warn);

} else if (c.begin_refs () == c.end_refs () || a.begin_pins () == a.end_pins () || b.begin_pins () == b.end_pins ()) {

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));
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));
warn.set_cell_name (c.name ());
warn.set_geometry (subcircuit_geometry (*path.back (), internal_layout ()));
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 must be connected further up in the hierarchy - this is an error at chip top level")), a.expanded_name (), b.expanded_name ()));
warn.set_cell_name (c.name ());
warn.set_category_name ("must-connect");
log_entry (warn);
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));
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));
warn.set_cell_name (c.name ());
warn.set_geometry (subcircuit_geometry (*path.back (), internal_layout ()));
warn.set_category_name ("must-connect");
log_entry (warn);
}
}

}

if (a.begin_pins () != a.end_pins () && b.begin_pins () != b.end_pins ()) {

for (auto ref = c.begin_refs (); ref != c.end_refs (); ++ref) {

const db::SubCircuit &sc = *ref;

// TODO: consider the case of multiple pins on a net (rare)
const db::Net *net_a = sc.net_for_pin (a.begin_pins ()->pin_id ());
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.expanded_name (), c.name (), subcircuit_to_string (sc)));
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));
error.set_cell_name (sc.circuit ()->name ());
error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
error.set_category_name ("must-connect");
log_entry (error);
}

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.expanded_name (), c.name (), subcircuit_to_string (sc)));
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));
error.set_cell_name (sc.circuit ()->name ());
error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
error.set_category_name ("must-connect");
log_entry (error);
}

if (net_a && net_b && net_a != net_b) {
if (a.expanded_name () == b.expanded_name ()) {
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect nets %s of circuit %s are not connected%s")), a.expanded_name (), c.name (), subcircuit_to_string (sc)));
error.set_cell_name (sc.circuit ()->name ());
error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
error.set_category_name ("must-connect");
log_entry (error);
} else {
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s of circuit %s are not connected%s")), a.expanded_name (), b.expanded_name (), c.name (), subcircuit_to_string (sc)));
error.set_cell_name (sc.circuit ()->name ());
error.set_geometry (subcircuit_geometry (sc, internal_layout ()));
error.set_category_name ("must-connect");
log_entry (error);
}
path.push_back (&sc);
check_must_connect_impl (*sc.circuit (), *net_a, *net_b, c_org, a_org, b_org, path);
path.pop_back ();
}

}

}
}

Expand Down
1 change: 1 addition & 0 deletions src/db/db/dbLayoutToNetlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,7 @@ class DB_PUBLIC LayoutToNetlist
void join_nets_from_pattern (db::Circuit &c, const tl::GlobPattern &p);
void join_nets_from_pattern (db::Circuit &c, const std::set<std::string> &p);
void check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b);
void check_must_connect_impl (const db::Circuit &c, const db::Net &a, const db::Net &b, const db::Circuit &c_org, const db::Net &a_org, const db::Net &b_org, std::vector<const db::SubCircuit *> &path);

// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
Expand Down
14 changes: 0 additions & 14 deletions src/db/db/dbNetlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,20 +126,6 @@ void Netlist::set_case_sensitive (bool f)
m_case_sensitive = f;
}

int Netlist::name_compare (bool case_sensitive, const std::string &n1, const std::string &n2)
{
// TODO: unicode support?
if (case_sensitive) {
return strcmp (n1.c_str (), n2.c_str ());
} else {
#if defined(_WIN32)
return _stricmp (n1.c_str (), n2.c_str ());
#else
return strcasecmp (n1.c_str (), n2.c_str ());
#endif
}
}

std::string Netlist::normalize_name (bool case_sensitive, const std::string &n)
{
if (case_sensitive) {
Expand Down
5 changes: 0 additions & 5 deletions src/db/db/dbNetlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,6 @@ class DB_PUBLIC Netlist
*/
void combine_devices ();

/**
* @brief Compares two names with the given case sensitivity
*/
static int name_compare (bool case_sensitive, const std::string &n1, const std::string &n2);

/**
* @brief Normalizes a name with the given case sensitivity
*/
Expand Down
11 changes: 7 additions & 4 deletions src/db/db/dbNetlistCompareCore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,7 @@ static size_t distance3 (const NetGraphNode &a, const NetGraphNode &b1, const Ne
static void
analyze_nodes_for_close_matches (const std::multimap<size_t, const NetGraphNode *> &nodes_by_edges1, const std::multimap<size_t, const NetGraphNode *> &nodes_by_edges2, bool layout2ref, db::NetlistCompareLogger *logger, const db::NetGraph &g2)
{
size_t max_search = 100;
size_t max_search = 100000;
double max_fuzz_factor = 0.25;
size_t max_fuzz_count = 3;
size_t max_edges_split = 3; // by how many edges joining will reduce the edge count at max
Expand All @@ -1368,15 +1368,17 @@ analyze_nodes_for_close_matches (const std::multimap<size_t, const NetGraphNode
msg = tl::to_string (tr ("Connecting nets %s and %s is making a better match to net %s from reference netlist (fuzziness %d nodes)"));
}

for (auto i = nodes_by_edges1.begin (); i != nodes_by_edges1.end (); ++i) {
size_t tries = max_search;

for (auto i = nodes_by_edges1.begin (); i != nodes_by_edges1.end () && tries > 0; ++i) {

if (i->first < min_edges) {
continue;
}

std::set<const db::NetGraphNode *> seen;

for (auto j = nodes_by_edges2.begin (); j != nodes_by_edges2.end (); ++j) {
for (auto j = nodes_by_edges2.begin (); j != nodes_by_edges2.end () && tries > 0; ++j) {

seen.insert (j->second);

Expand Down Expand Up @@ -1407,7 +1409,6 @@ analyze_nodes_for_close_matches (const std::multimap<size_t, const NetGraphNode

auto k = nodes_by_edges2.lower_bound (ne);

size_t tries = max_search;
for ( ; k != nodes_by_edges2.end () && j->first + k->first < i->first + max_fuzz_count + max_edges_split && tries > 0; ++k) {

if (seen.find (k->second) != seen.end ()) {
Expand Down Expand Up @@ -1436,6 +1437,8 @@ analyze_nodes_for_close_matches (const std::multimap<size_t, const NetGraphNode
void
NetlistCompareCore::analyze_failed_matches () const
{
tl::SelfTimer timer (tl::verbosity () >= 21, "Analyzing failed matches");

// Determine the range of nodes with same identity

std::vector<NetGraphNode::edge_type> no_edges;
Expand Down
33 changes: 32 additions & 1 deletion src/db/db/dbNetlistCompareUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,40 @@ const std::string &extended_net_name (const db::Net *n)
}
}

static int net_name_compare (bool case_sensitive, const std::string &n1, const std::string &n2)
{
const char *n1p = n1.c_str ();
const char *n2p = n2.c_str ();

while (*n1p && *n2p) {

uint32_t c1 = tl::utf32_from_utf8 (n1p);
uint32_t c2 = tl::utf32_from_utf8 (n2p);

if (! case_sensitive) {
c1 = tl::utf32_downcase (c1);
c2 = tl::utf32_downcase (c2);
}

if (c1 != c2) {
return c1 < c2 ? -1 : 1;
}

}

// colon terminates net name, such that NET:I is identical to NET.
if (*n2p && *n2p != ':') {
return -1;
} else if (*n1p && *n1p != ':') {
return 1;
} else {
return 0;
}
}

int name_compare (const db::Net *a, const db::Net *b)
{
return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), extended_net_name (a), extended_net_name (b));
return net_name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), extended_net_name (a), extended_net_name (b));
}

bool net_names_are_different (const db::Net *a, const db::Net *b)
Expand Down
10 changes: 5 additions & 5 deletions src/db/db/dbNetlistCompareUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,30 +92,30 @@ std::string nets2string (const std::pair<const db::Net *, const db::Net *> &np);
/**
* @brief Derives the common case sensitivity for two netlists
*/
bool combined_case_sensitive (const db::Netlist *a, const db::Netlist *b);
DB_PUBLIC bool combined_case_sensitive (const db::Netlist *a, const db::Netlist *b);

/**
* @brief Gets the extended net name
* This name is used for comparing the net names and also employs the pin name if one is given
*/
const std::string &extended_net_name (const db::Net *n);
DB_PUBLIC const std::string &extended_net_name (const db::Net *n);

/**
* @brief Compare two nets by name
*/
int name_compare (const db::Net *a, const db::Net *b);
DB_PUBLIC int name_compare (const db::Net *a, const db::Net *b);

/**
* @brief Returns a value indicating whether two nets are different by name
* Two unnamed nets are never different.
*/
bool net_names_are_different (const db::Net *a, const db::Net *b);
DB_PUBLIC bool net_names_are_different (const db::Net *a, const db::Net *b);

/**
* @brief Returns a value indicating whether two nets are equal by name
* Two unnamed nets are never equal.
*/
bool net_names_are_equal (const db::Net *a, const db::Net *b);
DB_PUBLIC bool net_names_are_equal (const db::Net *a, const db::Net *b);

// --------------------------------------------------------------------------------------------------------------------
// DeviceCompare definition and implementation
Expand Down
Loading

0 comments on commit 8f8a7d0

Please sign in to comment.