Merge pull request #1720 from KLayout/bugfix/issue-1719

Bugfix/issue 1719
This commit is contained in:
Matthias Köfferlein 2024-05-31 22:48:09 +02:00 committed by GitHub
commit 7b2a248484
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 1414 additions and 231 deletions

View File

@ -2817,6 +2817,18 @@ private:
std::map<size_t, entry_list::iterator> m_global_net_to_entries;
};
template <class T>
struct is_for_nets
{
static bool value () { return false; }
};
template <>
struct is_for_nets<db::NetShape>
{
static bool value () { return true; }
};
}
template <class T>
@ -2903,11 +2915,34 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
}
bs2.process (*rec, 1 /*touching*/, local_cluster_box_convert<T> (), cibc);
}
// join local clusters which got connected by child clusters
rec->finish_cluster_to_instance_interactions ();
if (is_for_nets<T>::value ()) {
// remove empty or point-like clusters which do not make a downward connection - i.e. from stray texts.
// This implies, we cannot connect from upward down to such nets too. In other words: to force a pin,
// inside a cell we need more than a text.
// (issue #1719, part 2)
std::vector<typename local_cluster<T>::id_type> to_delete;
for (typename connected_clusters<T>::const_iterator c = local.begin (); c != local.end (); ++c) {
box_type bbox = c->bbox ();
if ((bbox.empty () || (bbox.width () == 0 && bbox.height () == 0)) && c->get_global_nets ().empty () && local.connections_for_cluster (c->id ()).empty ()) {
to_delete.push_back (c->id ());
}
}
for (auto i = to_delete.begin (); i != to_delete.end (); ++i) {
local.remove_cluster (*i);
}
if (tl::verbosity () >= m_base_verbosity + 20) {
tl::info << "Removed " << to_delete.size () << " clusters because they are point-like or empty and do not have connections downward (stray texts)";
}
}
if (tl::verbosity () >= m_base_verbosity + 20) {
tl::info << "Cluster build cache statistics (instance to shape cache): size=" << rec->cluster_cache_size () << ", hits=" << rec->cluster_cache_hits () << ", misses=" << rec->cluster_cache_misses ();
}

View File

@ -508,12 +508,37 @@ void LayoutToNetlist::do_join_nets (db::Circuit &c, const std::vector<db::Net *>
return;
}
check_must_connect (c, nets);
for (auto n = nets.begin () + 1; n != nets.end (); ++n) {
check_must_connect (c, *nets [0], **n);
c.join_nets (nets [0], *n);
}
}
void LayoutToNetlist::check_must_connect (const db::Circuit &c, const std::vector<db::Net *> &nets)
{
std::vector<const db::Net *> unique_nets;
unique_nets.reserve (nets.size ());
std::set<const db::Net *> seen;
for (auto n = nets.begin (); n != nets.end (); ++n) {
if (seen.find (*n) == seen.end ()) {
seen.insert (*n);
unique_nets.push_back (*n);
}
}
if (unique_nets.size () < size_t (2)) {
return;
}
bool same_names = true;
for (auto n = unique_nets.begin () + 1; n != unique_nets.end () && same_names; ++n) {
same_names = (unique_nets.front ()->expanded_name () == (*n)->expanded_name ());
}
std::vector<const db::SubCircuit *> path;
check_must_connect_impl (c, unique_nets, c, unique_nets, path, same_names);
}
static std::string subcircuit_to_string (const db::SubCircuit &sc)
{
if (! sc.name ().empty ()) {
@ -533,14 +558,31 @@ static db::DPolygon subcircuit_geometry (const db::SubCircuit &sc, const db::Lay
return db::DPolygon (sc.trans () * dbox);
}
void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b)
static db::DBox net_geometry_box (const db::Circuit &c, const db::Net *net, const db::Layout *layout, const db::hier_clusters<db::NetShape> &net_clusters)
{
if (&a == &b) {
return;
if (! layout || ! net) {
return db::DBox ();
}
std::vector<const db::SubCircuit *> path;
check_must_connect_impl (c, a, b, c, a, b, path);
auto nc = net_clusters.clusters_per_cell (c.cell_index ());
auto lc = nc.cluster_by_id (net->cluster_id ());
return db::CplxTrans (layout->dbu ()) * lc.bbox ();
}
static db::DPolygon net_geometry (const db::Circuit &c, const db::Net *net, const db::Layout *layout, const db::hier_clusters<db::NetShape> &net_clusters)
{
auto box = net_geometry_box (c, net, layout, net_clusters);
return box.empty () ? db::DPolygon () : db::DPolygon (box);
}
static db::DPolygon net_geometry (const db::Circuit &c, const std::vector<const db::Net *> &nets, const db::Layout *layout, const db::hier_clusters<db::NetShape> &net_clusters)
{
db::DBox box;
for (auto n = nets.begin (); n != nets.end (); ++n) {
box += net_geometry_box (c, *n, layout, net_clusters);
}
return box.empty () ? db::DPolygon () : db::DPolygon (box);
}
static std::string path_msg (const std::vector<const db::SubCircuit *> &path)
@ -562,46 +604,98 @@ static std::string path_msg (const std::vector<const db::SubCircuit *> &path)
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)
static bool all_nets_are_same (const std::vector<const db::Net *> &nets)
{
for (auto n = nets.begin () + 1; n != nets.end (); ++n) {
if (*n != nets.front ()) {
return false;
}
}
return true;
}
static bool no_pins_on_any_net (const std::vector<const db::Net *> &nets)
{
for (auto n = nets.begin (); n != nets.end (); ++n) {
if ((*n)->begin_pins () == (*n)->end_pins ()) {
return true;
}
}
return false;
}
static std::string net_names_msg (const std::vector<const db::Net *> &nets)
{
std::set<std::string> names;
for (auto n = nets.begin (); n != nets.end (); ++n) {
names.insert ((*n)->expanded_name ());
}
std::string msg;
size_t num = names.size ();
size_t i = 0;
for (auto n = names.begin (); n != names.end (); ++n, ++i) {
if (i > 0) {
if (i + 1 < num) {
msg += ", ";
} else {
msg += tl::to_string (tr (" and "));
}
}
msg += *n;
}
return msg;
}
void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const std::vector<const db::Net *> &nets, const db::Circuit &c_org, const std::vector<const db::Net *> &nets_org, std::vector<const db::SubCircuit *> &path, bool same_names)
{
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_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_org.expanded_name ()));
error.set_cell_name (c.name ());
error.set_category_name ("must-connect");
log_entry (error);
for (auto n = nets.begin (); n != nets.end (); ++n) {
if ((*n)->begin_pins () == (*n)->end_pins ()) {
std::string msg;
if (same_names) {
msg = tl::sprintf (tl::to_string (tr ("Must-connect subnet of %s does not have any pin at all")), (*n)->expanded_name ());
} else {
msg = tl::sprintf (tl::to_string (tr ("Must-connect net %s does not have any pin at all")), (*n)->expanded_name ());
}
db::LogEntryData error (db::Error, msg);
error.set_cell_name (c.name ());
error.set_geometry (net_geometry (c, *n, internal_layout (), net_clusters ()));
error.set_category_name ("must-connect");
log_entry (error);
}
}
} else if (c.begin_refs () == c.end_refs () || a.begin_pins () == a.end_pins () || b.begin_pins () == b.end_pins ()) {
} else if (c.begin_refs () == c.end_refs () || no_pins_on_any_net (nets)) {
if (a_org.expanded_name () == b_org.expanded_name ()) {
if (same_names) {
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));
db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect subnets of %s must be connected further up in the hierarchy - this is an error at chip top level")), nets_org.front ()->expanded_name ()) + path_msg (path));
warn.set_cell_name (c.name ());
warn.set_geometry (net_geometry (c, nets, internal_layout (), net_clusters ()));
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));
db::LogEntryData warn (m_top_level_mode ? db::Error : db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect subnets of %s of circuit %s must be connected further up in the hierarchy - this is an error at chip top level")), nets_org.front ()->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");
log_entry (warn);
}
} else {
std::string net_names = net_names_msg (nets_org);
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));
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")), net_names) + path_msg (path));
warn.set_cell_name (c.name ());
warn.set_geometry (net_geometry (c, nets, internal_layout (), net_clusters ()));
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));
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")), net_names, 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");
@ -611,35 +705,49 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N
}
if (a.begin_pins () != a.end_pins () && b.begin_pins () != b.end_pins ()) {
if (! no_pins_on_any_net (nets)) {
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 ());
std::vector<const db::Net *> new_nets;
new_nets.reserve (nets.size ());
bool failed = false;
std::set<const db::Net *> seen;
size_t i = 0;
for (auto n = nets.begin (); n != nets.end (); ++n, ++i) {
if (seen.find (*n) != seen.end ()) {
continue;
}
seen.insert (*n);
const db::Net *new_net = sc.net_for_pin ((*n)->begin_pins ()->pin_id ());
new_nets.push_back (new_net);
if (new_net == 0) {
failed = true;
std::string msg;
if (same_names) {
msg = tl::sprintf (tl::to_string (tr ("Must-connect subnet of %s of circuit %s has no outside connection at all%s")), nets_org[i]->expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path);
} else {
msg = tl::sprintf (tl::to_string (tr ("Must-connect net %s of circuit %s has no outside connection at all%s")), nets_org[i]->expanded_name (), c_org.name (), subcircuit_to_string (sc)) + path_msg (path);
}
db::LogEntryData error (db::Error, msg);
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 == 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));
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_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");
log_entry (error);
}
if (net_a && net_b && net_a != net_b) {
if (! failed && ! all_nets_are_same (new_nets)) {
path.push_back (&sc);
check_must_connect_impl (*sc.circuit (), *net_a, *net_b, c_org, a_org, b_org, path);
check_must_connect_impl (*sc.circuit (), new_nets, c_org, nets_org, path, same_names);
path.pop_back ();
}
@ -910,7 +1018,7 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n_in);
}
// Caution: this make create names which clash with future explicit names. Hopefully, the generated names are unique enough.
// Caution: this may create names which clash with future explicit names. Hopefully, the generated names are unique enough.
std::string n = n_in.empty () ? make_new_name () : n_in;
db::DeepLayer dl;

View File

@ -1109,8 +1109,8 @@ private:
void do_soft_connections ();
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);
void check_must_connect (const db::Circuit &c, const std::vector<Net *> &nets);
void check_must_connect_impl (const db::Circuit &c, const std::vector<const Net *> &nets, const db::Circuit &c_org, const std::vector<const Net *> &nets_org, std::vector<const db::SubCircuit *> &path, bool same_names);
// for debugging and testing
void place_soft_connection_diodes ();

View File

@ -86,14 +86,17 @@ NetlistComparer::exclude_resistors (double threshold)
void
NetlistComparer::same_nets (const db::Net *na, const db::Net *nb, bool must_match)
{
tl_assert (na && na);
m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (std::make_pair (na, nb), must_match));
if (na || nb) {
m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (std::make_pair (na, nb), must_match));
}
}
void
NetlistComparer::same_nets (const db::Circuit *ca, const db::Circuit *cb, const db::Net *na, const db::Net *nb, bool must_match)
{
m_same_nets [std::make_pair (ca, cb)].push_back (std::make_pair (std::make_pair (na, nb), must_match));
if (na || nb) {
m_same_nets [std::make_pair (ca, cb)].push_back (std::make_pair (std::make_pair (na, nb), must_match));
}
}
void
@ -207,6 +210,49 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
return res;
}
/**
* @brief Returns a consolidated list of identical nets for a circuit pair (aka "same_nets")
*
* The list is reduced by duplicates of the first net such, that the
* last "same_nets" entry wins.
*
* The return value is a list of net pairs and a flag indicating "must_match" mode.
* The second net can be null if "must_match" is true, indicating that no schematic
* net with the same name was found - hence a mismatch exists.
*/
std::vector<std::pair<std::pair<const Net *, const Net *>, bool> >
NetlistComparer::get_net_identity (const db::Circuit *ca, const db::Circuit *cb) const
{
std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > net_identity;
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
if (sn != m_same_nets.end ()) {
const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > &ni = sn->second;
// take last definition for a given first net
net_identity.reserve (ni.size ());
std::set<const Net *> seen;
for (auto i = ni.end (); i != ni.begin (); ) {
--i;
const Net *main_net = i->first.first ? i->first.first : i->first.second;
const Net *other_net = i->first.first ? i->first.second : i->first.first;
if (seen.find (main_net) == seen.end () && (! other_net || seen.find (other_net) == seen.end ())) {
net_identity.push_back (*i);
seen.insert (main_net);
if (other_net) {
seen.insert (other_net);
}
}
}
std::reverse (net_identity.begin (), net_identity.end ());
}
return net_identity;
}
bool
NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
{
@ -344,13 +390,6 @@ NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
tl_assert (i->second.second.size () == size_t (1));
const db::Circuit *cb = i->second.second.front ();
std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > empty;
const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > *net_identity = &empty;
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
if (sn != m_same_nets.end ()) {
net_identity = &sn->second;
}
if (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) {
if (db::NetlistCompareGlobalOptions::options ()->debug_netcompare) {
@ -362,7 +401,7 @@ NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
}
bool pin_mismatch = false;
bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, circuit_pin_mapper, *net_identity, pin_mismatch, c12_pin_mapping, c22_pin_mapping);
bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, circuit_pin_mapper, get_net_identity (ca, cb), pin_mismatch, c12_pin_mapping, c22_pin_mapping);
if (! g) {
good = false;
}
@ -899,8 +938,16 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
if (mp_logger) {
if (p->second && ! exact_match) {
if (m_with_log) {
mp_logger->log_entry (db::Error,
tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
if (! p->first.first) {
mp_logger->log_entry (db::Error,
tl::sprintf (tl::to_string (tr ("Right-side net %s is paired explicitly with a left-side one, but no net is present there")), expanded_name (p->first.second)));
} else if (! p->first.second) {
mp_logger->log_entry (db::Error,
tl::sprintf (tl::to_string (tr ("Left-side net %s is paired explicitly with a right-side one, but no net is present there")), expanded_name (p->first.first)));
} else {
mp_logger->log_entry (db::Error,
tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
}
}
mp_logger->net_mismatch (p->first.first, p->first.second);
} else {
@ -911,7 +958,11 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
} else if (p->second && g1.has_node_index_for_net (p->first.first)) {
if (mp_logger) {
mp_logger->net_mismatch (p->first.first, 0);
mp_logger->net_mismatch (p->first.first, p->first.second);
if (m_with_log && p->first.second) {
mp_logger->log_entry (db::Error,
tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
}
}
size_t ni1 = g1.node_index_for_net (p->first.first);
@ -920,7 +971,11 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
} else if (p->second && g2.has_node_index_for_net (p->first.second)) {
if (mp_logger) {
mp_logger->net_mismatch (0, p->first.second);
mp_logger->net_mismatch (p->first.first, p->first.second);
if (m_with_log && p->first.first) {
mp_logger->log_entry (db::Error,
tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
}
}
size_t ni2 = g2.node_index_for_net (p->first.second);

View File

@ -387,6 +387,7 @@ protected:
void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, db::DeviceEquivalenceTracker &device_eq, bool &good) const;
void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinCategorizer &circuit_pin_mapper, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, db::SubCircuitEquivalenceTracker &subcircuit_eq, bool &good) const;
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > get_net_identity (const db::Circuit *ca, const db::Circuit *cb) const;
mutable NetlistCompareLogger *mp_logger;
bool m_with_log;

View File

@ -73,7 +73,7 @@ nl_compare_debug_indent (size_t depth)
const std::string var_sep = tl::to_string (tr (" vs. "));
static std::string
std::string
expanded_name (const db::Net *a)
{
if (a == 0) {

View File

@ -83,6 +83,7 @@ const size_t unknown_id = std::numeric_limits<size_t>::max () - 1;
// Some utilities
std::string nl_compare_debug_indent (size_t depth);
std::string expanded_name (const db::Net *a);
std::string nets2string (const db::Net *a, const db::Net *b);
std::string nets2string (const std::pair<const db::Net *, const db::Net *> &np);

View File

@ -1451,7 +1451,7 @@ nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern)
}
for (db::Circuit::const_net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
const db::Net *net = n.operator-> ();
if (glob.match (net->name ())) {
if (!net->name ().empty () && glob.match (net->name ())) {
res.push_back (net);
}
}
@ -1480,7 +1480,7 @@ nets_by_name_const_from_netlist (const db::Netlist *netlist, const std::string &
for (auto n = c->begin_nets (); n != c->end_nets (); ++n) {
const db::Net *net = n.operator-> ();
// NOTE: we only pick root nets (pin_count == 0 or in top cell)
if ((is_top || net->pin_count () == 0) && glob.match (net->name ())) {
if ((is_top || net->pin_count () == 0) && !net->name ().empty () && glob.match (net->name ())) {
res.push_back (net);
}
}

View File

@ -1175,6 +1175,24 @@ four-terminal MOS transistor.
See <class_doc href="DeviceExtractorMOS4Transistor">DeviceExtractorMOS4Transistor</class_doc> for more details
about this extractor (non-strict mode applies for 'mos4').
</p>
<a name="name"/><h2>"name" - Assigns a name to a layer for reference in the LVS database</h2>
<keyword name="name"/>
<p>Usage:</p>
<ul>
<li><tt>name(layer, name)</tt></li>
</ul>
<p>
See <a href="/about/drc_ref_netter.xml#name">Netter#name</a> for a description of that function.
</p>
<a name="name_prefix"/><h2>"name_prefix" - Specifies the layer name prefix for auto-generated layer names</h2>
<keyword name="name_prefix"/>
<p>Usage:</p>
<ul>
<li><tt>name_prefix(prefix)</tt></li>
</ul>
<p>
See <a href="/about/drc_ref_netter.xml#name_prefix">Netter#name_prefix</a> for a description of that function.
</p>
<a name="netlist"/><h2>"netlist" - Obtains the extracted netlist from the default <a href="/about/drc_ref_netter.xml">Netter</a></h2>
<keyword name="netlist"/>
<p>

View File

@ -422,6 +422,49 @@ but no error is raised.
The <class_doc href="LayoutToNetlist">LayoutToNetlist</class_doc> object provides access to the internal details of
the netter object.
</p>
<a name="name"/><h2>"name" - Assigns a name to a layer</h2>
<keyword name="name"/>
<p>Usage:</p>
<ul>
<li><tt>name(layer, name)</tt></li>
</ul>
<p>
Layer names are listed in the LayoutToNetlist (L2N) or LVS database. They
are used to identify the layers, the net or device terminal geometries are
on. It is usual to have computed layers, so it is necessary to indicate the
purpose of the layer for later reuse of the geometries.
</p><p>
It is a good practice to assign names to computed and original layers,
for example:
</p><p>
<pre>
poly = input(...)
poly_resistor = input(...)
poly_wiring = poly - poly_resistor
name(poly_wiring, "poly_wiring")
</pre>
</p><p>
Names must be assigned before the layers are used for the first time
in <a href="#connect">connect</a>, <a href="#soft_connect">soft_connect</a>, <a href="#connect_global">connect_global</a>, <a href="#soft_connect_global">soft_connect_global</a> and
<a href="#extract_devices">extract_devices</a> statements.
</p><p>
If layers are not named, they will be given a name made from the
<a href="#name_prefix">name_prefix</a> and an incremental number when the layer is used for the
first time.
</p><p>
<a href="#name">name</a> can only be used once on a layer and the layer names must be
unique (not taken by another layer).
</p>
<a name="name_prefix"/><h2>"name_prefix" - Specifies the name prefix for auto-generated layer names</h2>
<keyword name="name_prefix"/>
<p>Usage:</p>
<ul>
<li><tt>name_prefix(prefix)</tt></li>
</ul>
<p>
See <link href="#name"/> for details. The default prefix is "l".
</p>
<a name="netlist"/><h2>"netlist" - Gets the extracted netlist or triggers extraction if not done yet</h2>
<keyword name="netlist"/>
<p>Usage:</p>

View File

@ -396,6 +396,9 @@ the schematic netlist for all circuits starting with "INV":
same_nets("INV*", "A*")
</pre>
</p><p>
A plain "*" for the net pattern forces all (named) nets to be equivalent between layout and schematic.
Unnamed nets from the extracted netlist are not considered - i.e. nets without a label.
</p><p>
After using this function, the compare algorithm will consider these nets equivalent.
Use this method to provide hints for the comparer in cases which are difficult to
resolve otherwise.
@ -404,6 +407,16 @@ circuit_a and net_a are for the layout netlist, circuit_b and net_b for the sche
Names are case sensitive for layout-derived netlists and case-insensitive for SPICE schematic netlists.
</p><p>
Use this method andwhere in the script before the <a href="#compare">compare</a> call.
</p><p>
Multiple calls of "same_nets" can be used. The calls are effective in the order
the are given. For example, the following sequence specifies equivalence of all
equally named nets, with the exception of "A" and "B" which are equivalent to each other
inside cell "ND2", despite their different name:
</p><p>
<pre>
same_nets("*", "*")
same_nets("ND2", "A", "B")
</pre>
</p>
<a name="same_nets!"/><h2>"same_nets!" - Establishes an equivalence between the nets with matching requirement</h2>
<keyword name="same_nets!"/>
@ -416,6 +429,22 @@ Use this method andwhere in the script before the <a href="#compare">compare</a>
<p>
This method is equivalent to <a href="#same_nets">same_nets</a>, but requires identity of the given nets.
If the specified nets do not match, an error is reported.
</p><p>
For example, this global specification requires all named nets from the
layout to have an equivalent net in the schematic and those nets need to be
identical for all circuits:
</p><p>
<pre>
same_nets!("*", "*")
</pre>
</p><p>
The following specification requires "A" and "B" to be identical in
circuit "ND2". It is not an error if either "A" does not exist in the
layout or "B" does not exist in the schematic:
</p><p>
<pre>
same_nets!("ND2", "A", "B")
</pre>
</p>
<a name="schematic"/><h2>"schematic" - Gets, sets or reads the reference netlist</h2>
<keyword name="schematic"/>

View File

@ -2394,6 +2394,18 @@ CODE
# @synopsis extract_devices(extractor_class, name, layer_hash)
# See \Netter#extract_devices for a description of that function.
# %DRC%
# @name name
# @brief Assigns a name to a layer for reference in the LVS database
# @synopsis name(layer, name)
# See \Netter#name for a description of that function.
# %DRC%
# @name name_prefix
# @brief Specifies the layer name prefix for auto-generated layer names
# @synopsis name_prefix(prefix)
# See \Netter#name_prefix for a description of that function.
# %DRC%
# @name netlist
# @brief Obtains the extracted netlist from the default \Netter
@ -2408,6 +2420,8 @@ CODE
connect_global
soft_connect
soft_connect_global
name_prefix
name
connect_implicit
connect_explicit
device_scaling

View File

@ -68,6 +68,7 @@ module DRC
@post_extract_config = []
@l2n = nil
@lnum = 0
@name_prefix = "l"
@device_scaling = 1.0
@ignore_extraction_errors = false
@top_level = false
@ -106,8 +107,8 @@ module DRC
a.requires_texts_or_region
b.requires_texts_or_region
register_layer(a.data)
register_layer(b.data)
_register_layer(a.data, "connect")
_register_layer(b.data, "connect")
a.data.is_a?(RBA::Region) && @l2n.connect(a.data)
b.data.is_a?(RBA::Region) && @l2n.connect(b.data)
@l2n.connect(a.data, b.data)
@ -150,8 +151,8 @@ module DRC
a.requires_texts_or_region
b.requires_texts_or_region
register_layer(a.data)
register_layer(b.data)
_register_layer(a.data, "soft_connect")
_register_layer(b.data, "soft_connect")
# soft connections imply hard intra-layer connections
a.data.is_a?(RBA::Region) && @l2n.connect(a.data)
b.data.is_a?(RBA::Region) && @l2n.connect(b.data)
@ -177,7 +178,7 @@ module DRC
l.is_a?(DRC::DRCLayer) || raise("Layer argument must be a layer")
l.requires_texts_or_region
register_layer(l.data)
_register_layer(l.data, "connect_global")
l.data.is_a?(RBA::Region) && @l2n.connect(l.data)
@l2n.connect_global(l.data, name)
@ -204,7 +205,7 @@ module DRC
l.is_a?(DRC::DRCLayer) || raise("Layer argument must be a layer")
l.requires_texts_or_region
register_layer(l.data)
_register_layer(l.data, "soft_connect_global")
l.data.is_a?(RBA::Region) && @l2n.connect(l.data)
@l2n.soft_connect_global(l.data, name)
@ -282,7 +283,7 @@ module DRC
layer_selection.keys.sort.each do |n|
l = layer_selection[n]
l.requires_texts_or_region
register_layer(l.data)
_register_layer(l.data, "extract_devices")
ls[n.to_s] = l.data
end
@ -294,6 +295,70 @@ module DRC
end
# %DRC%
# @name name
# @brief Assigns a name to a layer
# @synopsis name(layer, name)
# Layer names are listed in the LayoutToNetlist (L2N) or LVS database. They
# are used to identify the layers, the net or device terminal geometries are
# on. It is usual to have computed layers, so it is necessary to indicate the
# purpose of the layer for later reuse of the geometries.
#
# It is a good practice to assign names to computed and original layers,
# for example:
#
# @code
# poly = input(...)
# poly_resistor = input(...)
#
# poly_wiring = poly - poly_resistor
# name(poly_wiring, "poly_wiring")
# @/code
#
# Names must be assigned before the layers are used for the first time
# in \connect, \soft_connect, \connect_global, \soft_connect_global and
# \extract_devices statements.
#
# If layers are not named, they will be given a name made from the
# \name_prefix and an incremental number when the layer is used for the
# first time.
#
# \name can only be used once on a layer and the layer names must be
# unique (not taken by another layer).
# %DRC%
# @name name_prefix
# @brief Specifies the name prefix for auto-generated layer names
# @synopsis name_prefix(prefix)
# See \\name for details. The default prefix is "l".
def name(l, name)
@engine._context("name") do
l.is_a?(DRC::DRCLayer) || raise("First argument must be a layer")
(name.is_a?(String) && name != "") || raise("Second argument must be a non-empty string")
id = l.data.data_id
if @layers && @layers[id]
# already registered
if @layers[id][1] != name
raise("Layer already registered with name #{@layers[id][1]} in context: #{@layers[id][2]}")
end
return
end
self._register_layer(l.data, "name", name)
end
end
def name_prefix(prefix)
@name_prefix = prefix.to_s
end
# %DRC%
# @name device_scaling
# @brief Specifies a dimension scale factor for the geometrical device properties
@ -761,21 +826,30 @@ module DRC
@l2n.make_soft_connection_diodes = f
end
private
protected
def _register_layer(data, context, name = nil)
id = data.data_id
ensure_data
if @layers && @layers[id]
# already registered
return
end
if !name
@lnum += 1
name = @name_prefix + @lnum.to_s
end
@layers[id] = [ data, name, context ]
# every layer gets registered and intra-layer connections are made
@l2n.register(data, name)
def cleanup
@l2n && @l2n.is_extracted? && clear_connections
end
def ensure_data
if !@l2n
@layers = {}
_make_data
@l2n.device_scaling = @device_scaling
@l2n.top_level_mode = @top_level
end
end
def _make_data
if @engine._dss
@ -792,24 +866,21 @@ module DRC
end
def register_layer(data)
id = data.data_id
ensure_data
if @layers && @layers[id]
# already registered
return
end
@layers[id] = data
@lnum += 1
# every layer gets registered and intra-layer connections are made
@l2n.register(data, "l" + @lnum.to_s)
private
def cleanup
@l2n && @l2n.is_extracted? && clear_connections
end
def ensure_data
if !@l2n
@layers = {}
_make_data
@l2n.device_scaling = @device_scaling
@l2n.top_level_mode = @top_level
end
end
end
end

View File

@ -552,6 +552,9 @@ CODE
# same_nets("INV*", "A*")
# @/code
#
# A plain "*" for the net pattern forces all (named) nets to be equivalent between layout and schematic.
# Unnamed nets from the extracted netlist are not considered - i.e. nets without a label.
#
# After using this function, the compare algorithm will consider these nets equivalent.
# Use this method to provide hints for the comparer in cases which are difficult to
# resolve otherwise.
@ -560,6 +563,16 @@ CODE
# Names are case sensitive for layout-derived netlists and case-insensitive for SPICE schematic netlists.
#
# Use this method andwhere in the script before the \compare call.
#
# Multiple calls of "same_nets" can be used. The calls are effective in the order
# the are given. For example, the following sequence specifies equivalence of all
# equally named nets, with the exception of "A" and "B" which are equivalent to each other
# inside cell "ND2", despite their different name:
#
# @code
# same_nets("*", "*")
# same_nets("ND2", "A", "B")
# @/code
def same_nets(*args)
_same_nets_impl(false, *args)
@ -573,6 +586,22 @@ CODE
# @synopsis same_nets!(circuit_a, net_a, circuit_b, net_b)
# This method is equivalent to \same_nets, but requires identity of the given nets.
# If the specified nets do not match, an error is reported.
#
# For example, this global specification requires all named nets from the
# layout to have an equivalent net in the schematic and those nets need to be
# identical for all circuits:
#
# @code
# same_nets!("*", "*")
# @/code
#
# The following specification requires "A" and "B" to be identical in
# circuit "ND2". It is not an error if either "A" does not exist in the
# layout or "B" does not exist in the schematic:
#
# @code
# same_nets!("ND2", "A", "B")
# @/code
def same_nets!(*args)
_same_nets_impl(true, *args)
@ -655,7 +684,7 @@ CODE
nets = []
n2n.keys.sort.each do |n|
if force || (n2n[n][0] && n2n[n][1])
if n2n[n][0] && (force || n2n[n][1])
nets << n2n[n]
end
end

View File

@ -338,3 +338,22 @@ TEST(55_SoftConnectionSecondLevel)
{
run_test (_this, "soft_connect6", "soft_connect6.gds", true, false /*no LVS*/);
}
// Issue #1719, part 2 (ignore stray texts)
TEST(60_StrayTextsDoNotMakeNets)
{
run_test (_this, "stray_texts1", "stray_texts.gds", true, false /*no LVS*/);
}
// Issue #1719, part 2 (ignore stray texts)
TEST(61_StrayTextsDoNotMakeNets)
{
run_test (_this, "stray_texts2", "stray_texts.gds", true, false /*no LVS*/);
}
// Issue #1719, part 3 (layer naming)
TEST(62_LayerNames)
{
run_test (_this, "layer_names", "layer_names.gds", false, true, "TOP");
}

View File

@ -171,7 +171,7 @@ TEST(20_private)
TEST(21_private)
{
run_test (_this, "test_21.lylvs", "test_21.cir.gz", "test_21.gds.gz", true, "test_21_4.lvsdb");
run_test (_this, "test_21.lylvs", "test_21.cir.gz", "test_21.gds.gz", true, "test_21_5.lvsdb");
}
// issue #1021

View File

@ -47,7 +47,6 @@ X$14 4 BBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@ -55,7 +54,6 @@ X$14 4 BBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@ -63,7 +61,6 @@ X$14 4 BBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@ -71,5 +68,4 @@ X$14 4 BBGATEST
.SUBCKT BWBTEST 2
* net 1 B
* net 2 A
* net 3 BWBTEST
.ENDS BWBTEST

View File

@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
net(3 name(BWBTEST)
rect(l15 (754500 -114000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
net(3 name(FWBTEST)
rect(l3 (798000 565500) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
net(3 name(FBGATEST)
rect(l3 (-417000 610500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
net(3 name(BBGATEST)
rect(l15 (-422000 -313000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))

View File

@ -48,7 +48,6 @@ X$14 7 6 BBGATEST
.SUBCKT BBGATEST 1 2
* net 1 B
* net 2 A
* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@ -57,7 +56,6 @@ X$14 7 6 BBGATEST
.SUBCKT FBGATEST 1 2
* net 1 B
* net 2 A
* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@ -66,7 +64,6 @@ X$14 7 6 BBGATEST
.SUBCKT FWBTEST 1 2
* net 1 B
* net 2 A
* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@ -75,5 +72,4 @@ X$14 7 6 BBGATEST
.SUBCKT BWBTEST 1 2
* net 1 B
* net 2 A
* net 3 BWBTEST
.ENDS BWBTEST

View File

@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
net(3 name(BWBTEST)
rect(l15 (754500 -114000) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -83,9 +80,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
net(3 name(FWBTEST)
rect(l3 (798000 565500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -106,9 +100,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
net(3 name(FBGATEST)
rect(l3 (-417000 610500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -129,9 +120,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
net(3 name(BBGATEST)
rect(l15 (-422000 -313000) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))

View File

@ -47,7 +47,6 @@ X$14 4 BBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@ -55,7 +54,6 @@ X$14 4 BBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@ -63,7 +61,6 @@ X$14 4 BBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@ -71,5 +68,4 @@ X$14 4 BBGATEST
.SUBCKT BWBTEST 1
* net 1 B
* net 2 A
* net 3 BWBTEST
.ENDS BWBTEST

View File

@ -60,9 +60,6 @@ layout(
rect(l15 (830000 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
net(3 name(BWBTEST)
rect(l15 (757500 -114000) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
net(3 name(FWBTEST)
rect(l3 (798000 565500) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
net(3 name(FBGATEST)
rect(l3 (-417000 610500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
net(3 name(BBGATEST)
rect(l15 (-422000 -313000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))

View File

@ -20,7 +20,6 @@ X$13 4 BBGATEST
.SUBCKT BWBTEST
* net 1 B
* net 2 A
* net 3 BWBTEST
.ENDS BWBTEST
* cell FDPTEST
@ -52,7 +51,6 @@ X$13 4 BBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@ -60,7 +58,6 @@ X$13 4 BBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@ -68,5 +65,4 @@ X$13 4 BBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
* net 3 FWBTEST
.ENDS FWBTEST

View File

@ -60,9 +60,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
net(3 name(FWBTEST)
rect(l3 (798000 565500) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -82,9 +79,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
net(3 name(FBGATEST)
rect(l3 (-417000 610500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -104,9 +98,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
net(3 name(BBGATEST)
rect(l15 (-422000 -313000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -186,9 +177,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
net(3 name(BWBTEST)
rect(l15 (754500 -114000) (0 0))
)
)
circuit(testall

View File

@ -47,7 +47,6 @@ X$14 5 BWBTEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@ -55,7 +54,6 @@ X$14 5 BWBTEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@ -63,7 +61,6 @@ X$14 5 BWBTEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@ -71,5 +68,4 @@ X$14 5 BWBTEST
.SUBCKT BWBTEST 2
* net 1 B
* net 2 A
* net 3 BWBTEST
.ENDS BWBTEST

View File

@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
net(3 name(BWBTEST)
rect(l15 (754500 -114000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
net(3 name(FWBTEST)
rect(l3 (798000 565500) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
net(3 name(FBGATEST)
rect(l3 (-417000 610500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
net(3 name(BBGATEST)
rect(l15 (-422000 -313000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))

View File

@ -47,7 +47,6 @@ X$14 3 FBGATEST
.SUBCKT BBGATEST 2
* net 1 B
* net 2 A
* net 3 BBGATEST
.ENDS BBGATEST
* cell FBGATEST
@ -55,7 +54,6 @@ X$14 3 FBGATEST
.SUBCKT FBGATEST 1
* net 1 B
* net 2 A
* net 3 FBGATEST
.ENDS FBGATEST
* cell FWBTEST
@ -63,7 +61,6 @@ X$14 3 FBGATEST
.SUBCKT FWBTEST 2
* net 1 B
* net 2 A
* net 3 FWBTEST
.ENDS FWBTEST
* cell BWBTEST
@ -71,5 +68,4 @@ X$14 3 FBGATEST
.SUBCKT BWBTEST 2
* net 1 B
* net 2 A
* net 3 BWBTEST
.ENDS BWBTEST

View File

@ -60,9 +60,6 @@ layout(
rect(l15 (576500 -249000) (105500 81500))
rect(l15 (-52750 -40750) (0 0))
)
net(3 name(BWBTEST)
rect(l15 (754500 -114000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -82,9 +79,6 @@ layout(
rect(l3 (572500 432500) (74500 73500))
rect(l3 (-37250 -36750) (0 0))
)
net(3 name(FWBTEST)
rect(l3 (798000 565500) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))
@ -104,9 +98,6 @@ layout(
rect(l3 (-449500 422500) (146000 144500))
rect(l3 (-71000 -71250) (0 0))
)
net(3 name(FBGATEST)
rect(l3 (-417000 610500) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name(B))
@ -126,9 +117,6 @@ layout(
rect(l15 (-218500 -290000) (193000 203000))
rect(l15 (-94000 -101500) (0 0))
)
net(3 name(BBGATEST)
rect(l15 (-422000 -313000) (0 0))
)
# Outgoing pins and their connections to nets
pin(2 name(A))

View File

@ -185,10 +185,9 @@ xref(
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets $1 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets 7 are paired explicitly, but are not identical topologically'))
)
xref(
net(() 7 mismatch)
net(1 () mismatch)
net(5 1 match)
net(4 2 match)
@ -196,8 +195,10 @@ xref(
net(3 4 match)
net(7 5 match)
net(8 6 match)
net(9 7 mismatch)
net(6 8 match)
circuit(1 1 mismatch)
circuit(() 1 mismatch)
circuit(1 () mismatch)
)
)
)

View File

@ -181,9 +181,8 @@ xref(
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets (not connected) vs. 5 are paired explicitly, but are not identical topologically'))
entry(error description('Nets 5,7 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets (not connected) vs. 7 are paired explicitly, but are not identical topologically'))
entry(error description('Left-side net 5,7 is paired explicitly with a right-side one, but no net is present there'))
entry(error description('Net 5,7 is not matching any net from reference netlist'))
)
xref(
net(() 5 mismatch)

View File

@ -184,15 +184,11 @@ xref(
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets $1 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets (not connected) vs. 5 are paired explicitly, but are not identical topologically'))
entry(error description('Nets 5,7 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets (not connected) vs. 7 are paired explicitly, but are not identical topologically'))
entry(error description('Left-side net 5,7 is paired explicitly with a right-side one, but no net is present there'))
)
xref(
net(() 5 mismatch)
net(() 7 mismatch)
net(1 () mismatch)
net(1 7 match)
net(5 1 match)
net(4 2 match)
net(2 3 match)

View File

@ -27,9 +27,9 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(W B('Must-connect nets GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
H(W B('Must-connect nets R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
H(W B('Must-connect nets R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
H(W B('Must-connect subnets of GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(0.27,0.8;0.27,8.4;0.32,8.4;0.32,0.8)'))
H(W B('Must-connect subnets of R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(1.48,2.37;1.48,7.46;2.61,7.46;2.61,2.37)'))
H(W B('Must-connect subnets of R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS

View File

@ -27,9 +27,9 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(W B('Must-connect nets GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
H(W B('Must-connect nets R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect'))
H(W B('Must-connect nets R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
H(W B('Must-connect subnets of GND must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(0.27,0.8;0.27,8.4;0.32,8.4;0.32,0.8)'))
H(W B('Must-connect subnets of R must be connected further up in the hierarchy - this is an error at chip top level') C(INVCHAIN) X('must-connect') Q('(1.48,2.37;1.48,7.46;2.61,7.46;2.61,2.37)'))
H(W B('Must-connect subnets of R of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$1') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS

50
testdata/lvs/layer_names.cir vendored Normal file
View File

@ -0,0 +1,50 @@
* Extracted by KLayout
* cell TOP
* pin A
* pin C
* pin SUBSTRATE
.SUBCKT TOP 2 3 4
* net 2 A
* net 3 C
* net 4 SUBSTRATE
* cell instance $1 r0 *1 0,0
X$1 2 3 1 6 4 DINV
* cell instance $2 r0 *1 3.6,0
X$2 5 6 1 4 INVX1
.ENDS TOP
* cell DINV
* pin A<1>
* pin A<2>
* pin B<2>
* pin VDD
* pin VSS
.SUBCKT DINV 1 2 3 5 6
* net 1 A<1>
* net 2 A<2>
* net 3 B<2>
* net 4 B<1>
* net 5 VDD
* net 6 VSS
* cell instance $1 r0 *1 0,0
X$1 4 5 1 6 INVX1
* cell instance $2 r0 *1 1.8,0
X$2 3 5 2 6 INVX1
.ENDS DINV
* cell INVX1
* pin OUT
* pin VDD
* pin IN
* pin VSS
.SUBCKT INVX1 1 2 3 4
* net 1 OUT
* net 2 VDD
* net 3 IN
* net 4 VSS
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 1 3 2 2 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $2 r0 *1 0.85,2.135 NMOS
M$2 1 3 4 4 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
.ENDS INVX1

BIN
testdata/lvs/layer_names.gds vendored Normal file

Binary file not shown.

105
testdata/lvs/layer_names.lvs vendored Normal file
View File

@ -0,0 +1,105 @@
source($lvs_test_source, $lvs_test_top)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("floating_ref.cir")
deep
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
pplus = input(3, 0)
nplus = input(4, 0)
poly = input(5, 0)
contact = input(8, 0)
metal1 = input(9, 0)
via1 = input(10, 0)
metal2 = input(11, 0)
# try layer names with nwell
name(nwell, "nwell")
# same name - not an error
name(nwell, "nwell")
ok = true
begin
name(nwell, "nwell2")
ok = false
rescue => ex
end
ok || raise("nwell layer is already named - this is an error")
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active & nwell
pactive = active_in_nwell & pplus
pgate = pactive & poly
psd = pactive - pgate
ntie = active_in_nwell & nplus
active_outside_nwell = active - nwell
nactive = active_outside_nwell & nplus
ngate = nactive & poly
nsd = nactive - ngate
ptie = active_outside_nwell & pplus
# Layer names for all other layers
%w(bulk pactive pgate psd ntie nactive ngate nsd poly contact metal1 via1 metal2).each do |v|
name(eval(v), v)
end
# Device extraction
# PMOS transistor device extraction
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
"tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
# NMOS transistor device extraction
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
"tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
# Define connectivity for netlist extraction
# Inter-layer
connect(psd, contact)
connect(nsd, contact)
connect(poly, contact)
connect(ntie, contact)
connect(nwell, ntie)
connect(ptie, contact)
connect(contact, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
connect_global(ptie, "SUBSTRATE")
ok = true
begin
name(ptie, "ptie")
ok = false
rescue => ex
end
ok || raise("ptie layer already used - this is an error")
# Compare section
netlist.simplify
align
consider_net_names(false)
compare

434
testdata/lvs/layer_names.lvsdb vendored Normal file
View File

@ -0,0 +1,434 @@
#%lvsdb-klayout
# Layout
layout(
top(TOP)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(nwell '1/0')
layer(poly '5/0')
layer(contact '8/0')
layer(metal1 '9/0')
layer(via1)
layer(metal2)
layer(bulk)
layer(psd)
layer(ntie)
layer(nsd)
layer(l1)
# Mask layer connectivity
connect(nwell nwell ntie)
connect(poly poly contact)
connect(contact poly contact metal1 psd ntie nsd l1)
connect(metal1 contact metal1 via1)
connect(via1 metal1 via1 metal2)
connect(metal2 via1 metal2)
connect(bulk bulk)
connect(psd contact psd)
connect(ntie nwell contact ntie)
connect(nsd contact nsd)
connect(l1 contact l1)
# Global nets and connectivity
global(bulk SUBSTRATE)
global(l1 SUBSTRATE)
# Device class section
class(PMOS MOS4)
class(NMOS MOS4)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$PMOS PMOS
terminal(S
rect(psd (-550 -750) (425 1500))
)
terminal(G
rect(poly (-125 -750) (250 1500))
)
terminal(D
rect(psd (125 -750) (425 1500))
)
terminal(B
rect(nwell (-125 -750) (250 1500))
)
)
device(D$NMOS NMOS
terminal(S
rect(nsd (-550 -475) (425 950))
)
terminal(G
rect(poly (-125 -475) (250 950))
)
terminal(D
rect(nsd (125 -475) (425 950))
)
terminal(B
rect(bulk (-125 -475) (250 950))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(INVX1
# Circuit boundary
rect((-100 400) (2000 7600))
# Nets with their geometries
net(1 name(OUT)
rect(contact (1110 5160) (180 180))
rect(contact (-180 920) (180 180))
rect(contact (-180 -730) (180 180))
rect(contact (-180 -4120) (180 180))
rect(contact (-180 370) (180 180))
rect(metal1 (-240 -790) (300 4790))
rect(metal1 (-150 -2500) (0 0))
rect(psd (-225 1050) (425 1500))
rect(nsd (-425 -4890) (425 950))
)
net(2 name(VDD)
rect(nwell (-100 4500) (2000 3500))
rect(contact (-1090 -890) (180 180))
rect(contact (-580 -1030) (180 180))
rect(contact (-180 -730) (180 180))
rect(contact (-180 -730) (180 180))
rect(metal1 (-590 1460) (1800 800))
rect(metal1 (-1050 -550) (300 300))
rect(metal1 (-700 -850) (300 300))
rect(metal1 (300 500) (0 0))
rect(metal1 (-600 -2200) (300 1400))
rect(psd (-350 -1450) (425 1500))
rect(ntie (-75 450) (500 500))
)
net(3 name(IN)
rect(poly (725 2860) (250 1940))
rect(poly (-525 -1850) (300 300))
rect(poly (-25 -1840) (250 1450))
rect(poly (-250 1940) (250 2000))
rect(poly (-250 -2000) (250 2000))
rect(contact (-465 -3790) (180 180))
rect(metal1 (-90 -90) (0 0))
rect(metal1 (-150 -150) (300 300))
)
net(4 name(VSS)
rect(contact (810 710) (180 180))
rect(contact (-580 880) (180 180))
rect(contact (-180 370) (180 180))
rect(metal1 (-590 -2100) (1800 800))
rect(metal1 (-1050 -550) (300 300))
rect(metal1 (-100 -150) (0 0))
rect(metal1 (-600 400) (300 1360))
rect(nsd (-350 -900) (425 950))
rect(l1 (-75 -2010) (500 400))
)
# Outgoing pins and their connections to nets
pin(1 name(OUT))
pin(2 name(VDD))
pin(3 name(IN))
pin(4 name(VSS))
# Devices and their connections
device(1 D$PMOS
location(850 5800)
param(L 0.25)
param(W 1.5)
param(AS 0.6375)
param(AD 0.6375)
param(PS 3.85)
param(PD 3.85)
terminal(S 2)
terminal(G 3)
terminal(D 1)
terminal(B 2)
)
device(2 D$NMOS
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.40375)
param(PS 2.75)
param(PD 2.75)
terminal(S 4)
terminal(G 3)
terminal(D 1)
terminal(B 4)
)
)
circuit(DINV
# Circuit boundary
rect((-100 400) (3800 7600))
# Nets with their geometries
net(1 name('A<1>')
rect(metal1 (600 3100) (0 0))
)
net(2 name('A<2>')
rect(metal1 (2400 3100) (0 0))
)
net(3 name('B<2>')
rect(metal1 (3000 4000) (0 0))
)
net(4 name('B<1>')
rect(metal1 (1200 4000) (0 0))
)
net(5 name(VDD)
rect(metal1 (1800 7200) (0 0))
)
net(6 name(VSS)
rect(metal1 (1800 800) (0 0))
)
# Outgoing pins and their connections to nets
pin(1 name('A<1>'))
pin(2 name('A<2>'))
pin(3 name('B<2>'))
pin(5 name(VDD))
pin(6 name(VSS))
# Subcircuits and their connections
circuit(1 INVX1 location(0 0)
pin(0 4)
pin(1 5)
pin(2 1)
pin(3 6)
)
circuit(2 INVX1 location(1800 0)
pin(0 3)
pin(1 5)
pin(2 2)
pin(3 6)
)
)
circuit(TOP
# Circuit boundary
rect((-100 400) (5600 7600))
# Nets with their geometries
net(1
rect(metal1 (3100 2950) (950 300))
)
net(2 name(A)
rect(metal1 (600 3100) (0 0))
)
net(3 name(C)
rect(metal1 (2400 3100) (0 0))
)
net(4 name(SUBSTRATE))
net(5)
net(6)
# Outgoing pins and their connections to nets
pin(2 name(A))
pin(3 name(C))
pin(4 name(SUBSTRATE))
# Subcircuits and their connections
circuit(1 DINV location(0 0)
pin(0 2)
pin(1 3)
pin(2 1)
pin(3 6)
pin(4 4)
)
circuit(2 INVX1 location(3600 0)
pin(0 5)
pin(1 6)
pin(2 1)
pin(3 4)
)
)
)
# Reference netlist
reference(
# Device class section
class(NMOS MOS4)
class(PMOS MOS4)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(INVX1
# Nets
net(1 name(A))
net(2 name(Z))
net(3 name(VSS))
net(4 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(A))
pin(2 name(Z))
pin(4 name(VDD))
pin(3 name(VSS))
# Devices and their connections
device(1 NMOS
name('0')
param(L 0.25)
param(W 0.95)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 3)
terminal(G 1)
terminal(D 2)
terminal(B 3)
)
device(2 PMOS
name('1')
param(L 0.25)
param(W 1.5)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 4)
terminal(G 1)
terminal(D 2)
terminal(B 4)
)
)
circuit(DINV
# Nets
net(1 name('A<1>'))
net(2 name('A<2>'))
net(3 name('B<1>'))
net(4 name('B<2>'))
net(5 name(VDD))
net(6 name(VSS))
# Outgoing pins and their connections to nets
pin(1 name('A<1>'))
pin(2 name('A<2>'))
pin(3 name('B<1>'))
pin(4 name('B<2>'))
pin(5 name(VDD))
pin(6 name(VSS))
# Subcircuits and their connections
circuit(1 INVX1 name(A)
pin(0 1)
pin(1 3)
pin(2 5)
pin(3 6)
)
circuit(2 INVX1 name(B)
pin(0 2)
pin(1 4)
pin(2 5)
pin(3 6)
)
)
circuit(TOP
# Nets
net(1 name(A))
net(2 name(C))
net(3 name(D))
net(4 name(B))
net(5 name(E))
net(6 name(VDD))
net(7 name(VSS))
# Outgoing pins and their connections to nets
pin(1 name(A))
pin(2 name(C))
pin(3 name(D))
pin(6 name(VDD))
pin(7 name(VSS))
# Subcircuits and their connections
circuit(1 DINV name('0')
pin(0 1)
pin(1 2)
pin(2 4)
pin(3 5)
pin(4 6)
pin(5 7)
)
circuit(2 INVX1 name('1')
pin(0 5)
pin(1 3)
pin(2 6)
pin(3 7)
)
)
)
# Cross reference
xref(
circuit(DINV DINV match
log(
entry(warning description('Matching nets B<1> from an ambiguous group of nets'))
entry(warning description('Matching nets B<2> from an ambiguous group of nets'))
entry(info description('Matching nets A<1> following an ambiguous match'))
entry(info description('Matching nets A<2> following an ambiguous match'))
)
xref(
net(1 1 match)
net(2 2 match)
net(4 3 warning)
net(3 4 warning)
net(5 5 match)
net(6 6 match)
pin(() 2 match)
pin(0 0 match)
pin(1 1 match)
pin(2 3 match)
pin(3 4 match)
pin(4 5 match)
circuit(1 1 match)
circuit(2 2 match)
)
)
circuit(INVX1 INVX1 match
xref(
net(3 1 match)
net(1 2 match)
net(2 4 match)
net(4 3 match)
pin(2 0 match)
pin(0 1 match)
pin(1 2 match)
pin(3 3 match)
device(2 1 match)
device(1 2 match)
)
)
circuit(TOP TOP match
xref(
net(5 3 match)
net(1 5 match)
net(6 6 match)
net(2 1 match)
net(3 2 match)
net(4 7 match)
pin(() 2 match)
pin(() 3 match)
pin(0 0 match)
pin(1 1 match)
pin(2 4 match)
circuit(1 1 match)
circuit(2 2 match)
)
)
)

View File

@ -27,7 +27,7 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(W B('Must-connect nets VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
H(W B('Must-connect subnets of VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(3.61,0.7;3.61,8.89;11.365,8.89;11.365,0.7)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS

View File

@ -27,7 +27,7 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(E B('Must-connect nets VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
H(E B('Must-connect subnets of VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(3.61,0.7;3.61,8.89;11.365,8.89;11.365,0.7)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS

View File

@ -27,9 +27,9 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(W B('Must-connect nets VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
H(W B('Must-connect nets VDD must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect'))
H(W B('Must-connect nets VSS of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$2') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
H(W B('Must-connect subnets of VSSTOP must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(3.61,0.7;3.61,8.89;11.365,8.89;11.365,0.7)'))
H(W B('Must-connect subnets of VDD must be connected further up in the hierarchy - this is an error at chip top level') C(TOP) X('must-connect') Q('(2.595,4.725;2.595,4.805;11.865,4.805;11.865,4.725)'))
H(W B('Must-connect subnets of VSS of circuit INV2 must be connected further up in the hierarchy - this is an error at chip top level.\nInstance path: INVCHAIN/INV2[r0 0,0]:$2') C(INVCHAIN) X('must-connect') Q('(0,0;0,9.2;3,9.2;3,0)'))
K(PMOS MOS3)
K(NMOS MOS3)
D(D$PMOS PMOS

View File

@ -39,7 +39,7 @@ layout(
global(l10 SUBSTRATE)
# Log entries
message(warning description('Must-connect nets VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect'))
message(warning description('Must-connect subnets of VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect') polygon('(2.95,7.25;2.95,7.4;25.1,7.4;25.1,7.25)'))
# Device class section
class(PMOS MOS4)

View File

@ -39,7 +39,7 @@ layout(
global(l10 SUBSTRATE)
# Log entries
message(warning description('Must-connect nets VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect'))
message(warning description('Must-connect subnets of VDD must be connected further up in the hierarchy - this is an error at chip top level') cell(RINGO) cat('must-connect') polygon('(2.95,7.25;2.95,7.4;25.1,7.4;25.1,7.25)'))
# Device class section
class(PMOS MOS4)

BIN
testdata/lvs/stray_texts.gds vendored Normal file

Binary file not shown.

12
testdata/lvs/stray_texts1.cir vendored Normal file
View File

@ -0,0 +1,12 @@
* Extracted by KLayout
.SUBCKT TOP
X$1 \$2 \$5 \$4 E \$1 MIDDLE
.ENDS TOP
.SUBCKT MIDDLE B \$I4 \$I3 \$I2 \$I1
X$1 \$I1 B \$I3 \$I4 \$I2 F CHILD
.ENDS MIDDLE
.SUBCKT CHILD A B C D \$8 \$9
.ENDS CHILD

98
testdata/lvs/stray_texts1.l2n vendored Normal file
View File

@ -0,0 +1,98 @@
#%l2n-klayout
W(TOP)
U(0.001)
L(l1 '1/0')
L(l2 '1/0')
L(l3 '2/0')
C(l1 l2 l3)
C(l2 l1 l2 l3)
C(l3 l1 l2 l3)
X(CHILD
R((-1230 410) (4330 220))
N(1 I(A)
J(l1 A (-560 550))
R(l2 (-80 -80) (170 160))
)
N(2 I(B)
J(l1 B (660 510))
J(l1 B (560 10))
R(l2 (-650 -90) (160 150))
R(l2 (410 -140) (140 160))
)
N(3 I(C)
J(l1 C (-1160 530))
R(l2 (-70 -90) (160 170))
)
N(4 I(D)
J(l1 D (1820 510))
R(l2 (-70 -90) (160 160))
)
N(5
R(l2 (2370 410) (170 200))
)
N(6
R(l2 (2910 430) (190 200))
)
P(1 I(A))
P(2 I(B))
P(3 I(C))
P(4 I(D))
P(5)
P(6)
)
X(MIDDLE
R((-1230 410) (4330 220))
N(1 I(B)
J(l1 B (640 520))
J(l1 B (550 0))
)
N(2 I(F)
J(l1 F (3000 510))
)
N(3)
N(4)
N(5)
N(6)
P(1 I(B))
P(3)
P(4)
P(5)
P(6)
X(1 CHILD Y(0 0)
P(0 6)
P(1 1)
P(2 4)
P(3 3)
P(4 5)
P(5 2)
)
)
X(TOP
R((-1280 -190) (4350 840))
N(1
R(l3 (-680 -160) (170 760))
R(l3 (-170 -790) (860 270))
R(l3 (-200 -270) (220 780))
)
N(2
R(l3 (530 -180) (220 790))
R(l3 (-220 -790) (790 180))
R(l3 (-260 -180) (260 810))
)
N(3 I(E)
J(l1 E (2400 460))
)
N(4
R(l3 (-1280 -150) (210 750))
)
N(5
R(l3 (1660 -190) (240 840))
)
X(1 MIDDLE Y(-30 -40)
P(0 2)
P(1 5)
P(2 4)
P(3 3)
P(4 1)
)
)

28
testdata/lvs/stray_texts1.lvs vendored Normal file
View File

@ -0,0 +1,28 @@
$lvs_test_source && source($lvs_test_source)
if $lvs_test_target_l2n
report_netlist($lvs_test_target_l2n)
else
report_netlist
end
writer = write_spice(true, false)
$lvs_test_target_cir && target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
deep
# separate labels and polygons
l1l = labels(1, 0)
l1 = polygons(1, 0)
l2 = input(2, 0)
connect(l1l, l1)
connect(l1l, l2)
connect(l1, l2)
connect_implicit("*", "*")
netlist

12
testdata/lvs/stray_texts2.cir vendored Normal file
View File

@ -0,0 +1,12 @@
* Extracted by KLayout
.SUBCKT TOP
X$1 \$2 \$5 \$4 E \$1 MIDDLE
.ENDS TOP
.SUBCKT MIDDLE B \$I4 \$I3 \$I2 \$I1
X$1 \$I1 B \$I3 \$I4 \$I2 F CHILD
.ENDS MIDDLE
.SUBCKT CHILD A B C D \$6 \$7
.ENDS CHILD

96
testdata/lvs/stray_texts2.l2n vendored Normal file
View File

@ -0,0 +1,96 @@
#%l2n-klayout
W(TOP)
U(0.001)
L(l1 '1/0')
L(l2 '2/0')
C(l1 l1 l2)
C(l2 l1 l2)
X(CHILD
R((-1230 410) (4330 220))
N(1 I(A)
R(l1 (-640 470) (170 160))
R(l1 (-90 -80) (0 0))
)
N(2 I(B)
R(l1 (570 430) (160 150))
R(l1 (-70 -70) (0 0))
R(l1 (480 -70) (140 160))
R(l1 (-60 -80) (0 0))
)
N(3 I(C)
R(l1 (-1230 440) (160 170))
R(l1 (-90 -80) (0 0))
)
N(4 I(D)
R(l1 (1750 420) (160 160))
R(l1 (-90 -70) (0 0))
)
N(5
R(l1 (2370 410) (170 200))
)
N(6
R(l1 (2910 430) (190 200))
)
P(1 I(A))
P(2 I(B))
P(3 I(C))
P(4 I(D))
P(5)
P(6)
)
X(MIDDLE
R((-1230 410) (4330 220))
N(1 I(B)
R(l1 (640 520) (0 0))
R(l1 (550 0) (0 0))
)
N(2 I(F)
R(l1 (3000 510) (0 0))
)
N(3)
N(4)
N(5)
N(6)
P(1 I(B))
P(3)
P(4)
P(5)
P(6)
X(1 CHILD Y(0 0)
P(0 6)
P(1 1)
P(2 4)
P(3 3)
P(4 5)
P(5 2)
)
)
X(TOP
R((-1280 -190) (4350 840))
N(1
R(l2 (-680 -160) (170 760))
R(l2 (-170 -790) (860 270))
R(l2 (-200 -270) (220 780))
)
N(2
R(l2 (530 -180) (220 790))
R(l2 (-220 -790) (790 180))
R(l2 (-260 -180) (260 810))
)
N(3 I(E)
R(l1 (2400 460) (0 0))
)
N(4
R(l2 (-1280 -150) (210 750))
)
N(5
R(l2 (1660 -190) (240 840))
)
X(1 MIDDLE Y(-30 -40)
P(0 2)
P(1 5)
P(2 4)
P(3 3)
P(4 1)
)
)

25
testdata/lvs/stray_texts2.lvs vendored Normal file
View File

@ -0,0 +1,25 @@
$lvs_test_source && source($lvs_test_source)
if $lvs_test_target_l2n
report_netlist($lvs_test_target_l2n)
else
report_netlist
end
writer = write_spice(true, false)
$lvs_test_target_cir && target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
deep
# polygons and labels on same layer
l1 = input(1, 0)
l2 = input(2, 0)
connect(l1, l2)
connect_implicit("*", "*")
netlist

View File

@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.385,-0.305;-0.385,5.855;9.105,5.855;9.105,-0.305)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)

View File

@ -71,7 +71,7 @@ layout(
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect'))
message(warning description('Must-connect subnets of vdd must be connected further up in the hierarchy - this is an error at chip top level') cell(SP6TArray_2X4) cat('must-connect') polygon('(-0.16,-0.13;-0.16,5.68;8.88,5.68;8.88,-0.13)'))
# Device class section
class(active_res RES)