From e96f20a1064840146f06c45dfe4abe3782607e40 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 22 May 2025 22:25:49 +0200 Subject: [PATCH] Introducing case sensitivity in circuit and netlist queries, makeing 'same_nets' more case sensitivity-aware in case of mixed sensitivity --- src/db/db/gsiDeclDbNetlist.cc | 78 ++++++++++++++-------- src/lvs/lvs/built-in-macros/_lvs_netter.rb | 8 +-- testdata/ruby/dbNetlist.rb | 32 +++++++++ 3 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 05e2c85bc..792d65d15 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1488,7 +1488,7 @@ nets_non_const (const std::vector &nc) } static std::vector -nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern) +nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern, const tl::Variant &cs) { std::vector res; if (! circuit) { @@ -1496,7 +1496,9 @@ nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern) } tl::GlobPattern glob (name_pattern); - if (circuit->netlist ()) { + if (! cs.is_nil ()) { + glob.set_case_sensitive (cs.to_bool ()); + } else if (circuit->netlist ()) { glob.set_case_sensitive (circuit->netlist ()->is_case_sensitive ()); } for (db::Circuit::const_net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) { @@ -1510,13 +1512,13 @@ nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern) } static std::vector -nets_by_name (db::Circuit *circuit, const std::string &name_pattern) +nets_by_name (db::Circuit *circuit, const std::string &name_pattern, const tl::Variant &cs) { - return nets_non_const (nets_by_name_const (circuit, name_pattern)); + return nets_non_const (nets_by_name_const (circuit, name_pattern, cs)); } static std::vector -nets_by_name_const_from_netlist (const db::Netlist *netlist, const std::string &name_pattern) +nets_by_name_const_from_netlist (const db::Netlist *netlist, const std::string &name_pattern, const tl::Variant &cs) { std::vector res; if (! netlist) { @@ -1524,7 +1526,7 @@ nets_by_name_const_from_netlist (const db::Netlist *netlist, const std::string & } tl::GlobPattern glob (name_pattern); - glob.set_case_sensitive (netlist->is_case_sensitive ()); + glob.set_case_sensitive (cs.is_nil () ? netlist->is_case_sensitive () : cs.to_bool ()); for (auto c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) { bool is_top = (c->begin_parents () == c->end_parents ()); for (auto n = c->begin_nets (); n != c->end_nets (); ++n) { @@ -1540,9 +1542,9 @@ nets_by_name_const_from_netlist (const db::Netlist *netlist, const std::string & } static std::vector -nets_by_name_from_netlist (db::Netlist *netlist, const std::string &name_pattern) +nets_by_name_from_netlist (db::Netlist *netlist, const std::string &name_pattern, const tl::Variant &cs) { - return nets_non_const (nets_by_name_const_from_netlist (netlist, name_pattern)); + return nets_non_const (nets_by_name_const_from_netlist (netlist, name_pattern, cs)); } Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", @@ -1658,17 +1660,25 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", "\n\n" "This constness variant has been introduced in version 0.26.8" ) + - gsi::method_ext ("nets_by_name", &nets_by_name, gsi::arg ("name_pattern"), + gsi::method_ext ("nets_by_name", &nets_by_name, gsi::arg ("name_pattern"), gsi::arg ("case_sensitive", tl::Variant (), "default"), "@brief Gets the net objects for a given name filter.\n" "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n" + "The 'case_sensitive' argument will control whether the name is looked up in a case sensitive way or not. Note that " + "with case insensitive search on a netlist that is case sensitive, the same name may render more than one hit. By " + "default, case sensitivity is taken from the netlist.\n" "\n" "This method has been introduced in version 0.27.3.\n" + "The 'case_sensitive' argument has been added in version 0.30.2." ) + - gsi::method_ext ("nets_by_name", &nets_by_name_const, gsi::arg ("name_pattern"), + gsi::method_ext ("nets_by_name", &nets_by_name_const, gsi::arg ("name_pattern"), gsi::arg ("case_sensitive", tl::Variant (), "default"), "@brief Gets the net objects for a given name filter (const version).\n" "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n" - "\n\n" - "This constness variant has been introduced in version 0.27.3" + "The 'case_sensitive' argument will control whether the name is looked up in a case sensitive way or not. Note that " + "with case insensitive search on a netlist that is case sensitive, the same name may render more than one hit. By " + "default, case sensitivity is taken from the netlist.\n" + "\n" + "This constness variant has been introduced in version 0.27.3.\n" + "The 'case_sensitive' argument has been added in version 0.30.2." ) + gsi::method ("pin_by_id", (db::Pin *(db::Circuit::*) (size_t)) &db::Circuit::pin_by_id, gsi::arg ("id"), "@brief Gets the \\Pin object corresponding to a specific ID\n" @@ -1964,7 +1974,7 @@ static void blank_circuit_by_name (db::Netlist *nl, const std::string &name_patt } static std::vector -circuits_by_name (db::Netlist *netlist, const std::string &name_pattern) +circuits_by_name (db::Netlist *netlist, const std::string &name_pattern, const tl::Variant &cs) { std::vector res; if (! netlist) { @@ -1972,7 +1982,7 @@ circuits_by_name (db::Netlist *netlist, const std::string &name_pattern) } tl::GlobPattern glob (name_pattern); - glob.set_case_sensitive (netlist->is_case_sensitive ()); + glob.set_case_sensitive (cs.is_nil () ? netlist->is_case_sensitive () : cs.to_bool ()); for (db::Netlist::circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) { db::Circuit *circuit = c.operator-> (); @@ -1985,7 +1995,7 @@ circuits_by_name (db::Netlist *netlist, const std::string &name_pattern) } static std::vector -circuits_by_name_const (const db::Netlist *netlist, const std::string &name_pattern) +circuits_by_name_const (const db::Netlist *netlist, const std::string &name_pattern, const tl::Variant &cs) { std::vector res; if (! netlist) { @@ -1993,7 +2003,7 @@ circuits_by_name_const (const db::Netlist *netlist, const std::string &name_patt } tl::GlobPattern glob (name_pattern); - glob.set_case_sensitive (netlist->is_case_sensitive ()); + glob.set_case_sensitive (cs.is_nil () ? netlist->is_case_sensitive () : cs.to_bool ()); for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) { const db::Circuit *circuit = c.operator-> (); @@ -2082,23 +2092,45 @@ Class decl_dbNetlist ("db", "Netlist", "\n\n" "This constness variant has been introduced in version 0.26.8." ) + - gsi::method_ext ("circuits_by_name", &circuits_by_name, gsi::arg ("name_pattern"), + gsi::method_ext ("circuits_by_name", &circuits_by_name, gsi::arg ("name_pattern"), gsi::arg ("case_sensitive", tl::Variant (), "default"), "@brief Gets the circuit objects for a given name filter.\n" "The name filter is a glob pattern. This method will return all \\Circuit objects matching the glob pattern.\n" + "The 'case_sensitive' argument will control whether the name is looked up in a case sensitive way or not. Note that " + "with case insensitive search on a netlist that is case sensitive, the same name may render more than one hit. By " + "default, case sensitivity is taken from the netlist.\n" "\n" "This method has been introduced in version 0.26.4.\n" + "The 'case_sensitive' argument has been added in version 0.30.2." ) + - gsi::method_ext ("circuits_by_name", &circuits_by_name_const, gsi::arg ("name_pattern"), + gsi::method_ext ("circuits_by_name", &circuits_by_name_const, gsi::arg ("name_pattern"), gsi::arg ("case_sensitive", tl::Variant (), "default"), "@brief Gets the circuit objects for a given name filter (const version).\n" "The name filter is a glob pattern. This method will return all \\Circuit objects matching the glob pattern.\n" - "\n\n" + "The 'case_sensitive' argument will control whether the name is looked up in a case sensitive way or not. Note that " + "with case insensitive search on a netlist that is case sensitive, the same name may render more than one hit. By " + "default, case sensitivity is taken from the netlist.\n" + "\n" "This constness variant has been introduced in version 0.26.8." + "The 'case_sensitive' argument has been added in version 0.30.2." ) + - gsi::method_ext ("nets_by_name", &nets_by_name_from_netlist, gsi::arg ("name_pattern"), + gsi::method_ext ("nets_by_name", &nets_by_name_from_netlist, gsi::arg ("name_pattern"), gsi::arg ("case_sensitive", tl::Variant (), "default"), "@brief Gets the net objects for a given name filter.\n" "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n" + "The 'case_sensitive' argument will control whether the name is looked up in a case sensitive way or not. Note that " + "with case insensitive search on a netlist that is case sensitive, the same name may render more than one hit. By " + "default, case sensitivity is taken from the netlist.\n" "\n" "This method has been introduced in version 0.28.4.\n" + "The 'case_sensitive' argument has been added in version 0.30.2." + ) + + gsi::method_ext ("nets_by_name", &nets_by_name_const_from_netlist, gsi::arg ("name_pattern"), gsi::arg ("case_sensitive", tl::Variant (), "default"), + "@brief Gets the net objects for a given name filter (const version).\n" + "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n" + "The 'case_sensitive' argument will control whether the name is looked up in a case sensitive way or not. Note that " + "with case insensitive search on a netlist that is case sensitive, the same name may render more than one hit. By " + "default, case sensitivity is taken from the netlist.\n" + "\n" + "This constness variant has been introduced in version 0.28.4." + "The 'case_sensitive' argument has been added in version 0.30.2." ) + gsi::method ("top_circuit", static_cast (&db::Netlist::top_circuit), "@brief Gets the top circuit.\n" @@ -2126,12 +2158,6 @@ Class decl_dbNetlist ("db", "Netlist", "\n" "This convenience method has been added in version 0.29.5." ) + - gsi::method_ext ("nets_by_name", &nets_by_name_const_from_netlist, gsi::arg ("name_pattern"), - "@brief Gets the net objects for a given name filter (const version).\n" - "The name filter is a glob pattern. This method will return all \\Net objects matching the glob pattern.\n" - "\n\n" - "This constness variant has been introduced in version 0.28.4." - ) + gsi::iterator ("each_circuit_top_down", (db::Netlist::top_down_circuit_iterator (db::Netlist::*) ()) &db::Netlist::begin_top_down, (db::Netlist::top_down_circuit_iterator (db::Netlist::*) ()) &db::Netlist::end_top_down, "@brief Iterates over the circuits top-down\n" "Iterating top-down means the parent circuits come before the child circuits. " diff --git a/src/lvs/lvs/built-in-macros/_lvs_netter.rb b/src/lvs/lvs/built-in-macros/_lvs_netter.rb index 4b3a44f7c..15e0dbbad 100644 --- a/src/lvs/lvs/built-in-macros/_lvs_netter.rb +++ b/src/lvs/lvs/built-in-macros/_lvs_netter.rb @@ -652,8 +652,8 @@ CODE if ca.is_a?(String) && (!cb || cb == "*") n2c = {} - nl_a.circuits_by_name(ca).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][0] = c } - nl_b.circuits_by_name(ca).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][1] = c } + nl_a.circuits_by_name(ca, cs).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][0] = c } + nl_b.circuits_by_name(ca, cs).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][1] = c } circuits = [] n2c.keys.sort.each do |n| @@ -679,8 +679,8 @@ CODE if a.is_a?(String) && (!b || b == "*") n2n = {} - circuit_a.nets_by_name(a).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][0] = n } - circuit_b.nets_by_name(a).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][1] = n } + circuit_a.nets_by_name(a, cs).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][0] = n } + circuit_b.nets_by_name(a, cs).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][1] = n } nets = [] n2n.keys.sort.each do |n| diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index aaf5e9cad..fa0b859e8 100644 --- a/testdata/ruby/dbNetlist.rb +++ b/testdata/ruby/dbNetlist.rb @@ -111,9 +111,17 @@ class DBNetlist_TestClass < TestBase assert_equal(nl.circuits_by_name("X*").collect { |x| x.name }, [ "XYZ" ]) assert_equal(nl.circuits_by_name("x*").collect { |x| x.name }, []) + assert_equal(nl.circuits_by_name("X*", true).collect { |x| x.name }, [ "XYZ" ]) + assert_equal(nl.circuits_by_name("x*", true).collect { |x| x.name }, []) + assert_equal(nl.circuits_by_name("X*", false).collect { |x| x.name }, [ "XYZ" ]) + assert_equal(nl.circuits_by_name("x*", false).collect { |x| x.name }, [ "XYZ" ]) nl.case_sensitive = false assert_equal(nl.circuits_by_name("X*").collect { |x| x.name }, [ "XYZ" ]) assert_equal(nl.circuits_by_name("x*").collect { |x| x.name }, [ "XYZ" ]) + assert_equal(nl.circuits_by_name("X*", true).collect { |x| x.name }, [ "XYZ" ]) + assert_equal(nl.circuits_by_name("x*", true).collect { |x| x.name }, []) + assert_equal(nl.circuits_by_name("X*", false).collect { |x| x.name }, [ "XYZ" ]) + assert_equal(nl.circuits_by_name("x*", false).collect { |x| x.name }, [ "XYZ" ]) nl.case_sensitive = true assert_equal(nl.circuits_by_name("???").collect { |x| x.name }, [ "XYZ", "UVW" ]) assert_equal(nl.circuits_by_name("*").collect { |x| x.name }, [ "XYZ", "UVW" ]) @@ -719,7 +727,31 @@ class DBNetlist_TestClass < TestBase assert_equal(c.net_by_name("net1").inspect, "nil") nl.case_sensitive = false assert_equal(c.net_by_name("net1").name, "NET1") + assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("net*").collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("NET*", true).collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("net*", true).collect(&:name), []) + assert_equal(c.nets_by_name("NET*", false).collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("net*", false).collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("NET*").collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("net*").collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("NET*", true).collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("net*", true).collect(&:name), []) + assert_equal(nl.nets_by_name("NET*", false).collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("net*", false).collect(&:name), ["NET1"]) nl.case_sensitive = true + assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("net*").collect(&:name), []) + assert_equal(c.nets_by_name("NET*", true).collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("net*", true).collect(&:name), []) + assert_equal(c.nets_by_name("NET*", false).collect(&:name), ["NET1"]) + assert_equal(c.nets_by_name("net*", false).collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("NET*").collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("net*").collect(&:name), []) + assert_equal(nl.nets_by_name("NET*", true).collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("net*", true).collect(&:name), []) + assert_equal(nl.nets_by_name("NET*", false).collect(&:name), ["NET1"]) + assert_equal(nl.nets_by_name("net*", false).collect(&:name), ["NET1"]) net2 = c.create_net net2.name = "NET2"