mirror of https://github.com/KLayout/klayout.git
A proposal for fixing issue #1719, part 1
This commit is contained in:
parent
14b1fddcc5
commit
3edb193562
|
|
@ -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 = ∅
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue