mirror of https://github.com/KLayout/klayout.git
395 lines
12 KiB
C++
395 lines
12 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2024 Matthias Koefferlein
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
#ifndef _HDR_dbNetlistCompareUtils
|
|
#define _HDR_dbNetlistCompareUtils
|
|
|
|
#include "dbCommon.h"
|
|
|
|
#include "tlEquivalenceClusters.h"
|
|
#include "tlProgress.h"
|
|
|
|
#include <string>
|
|
#include <limits>
|
|
#include <map>
|
|
#include <set>
|
|
|
|
namespace db
|
|
{
|
|
|
|
class Netlist;
|
|
class Net;
|
|
class SubCircuit;
|
|
class Device;
|
|
class DeviceClass;
|
|
class Circuit;
|
|
class SubCircuit;
|
|
class NetGraph;
|
|
class NetGraphNode;
|
|
class NetlistCompareLogger;
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// Global netlist compare options
|
|
|
|
struct DB_PUBLIC NetlistCompareGlobalOptions
|
|
{
|
|
NetlistCompareGlobalOptions ();
|
|
void ensure_initialized ();
|
|
|
|
bool debug_netcompare;
|
|
bool debug_netgraph;
|
|
|
|
static NetlistCompareGlobalOptions *options ();
|
|
|
|
private:
|
|
bool m_is_initialized;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// Some definitions for pseudo-Ids
|
|
|
|
// A constant indicating a failed match
|
|
const size_t failed_match = std::numeric_limits<size_t>::max ();
|
|
|
|
// A constant indicating an unknown match
|
|
// const size_t unknown_match = std::numeric_limits<size_t>::max () - 1;
|
|
|
|
// A constant indicating an invalid ID
|
|
const size_t invalid_id = std::numeric_limits<size_t>::max ();
|
|
|
|
// A constant indicating an unknown ID
|
|
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 nets2string (const db::Net *a, const db::Net *b);
|
|
std::string nets2string (const std::pair<const db::Net *, const db::Net *> &np);
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// Net name compare
|
|
|
|
/**
|
|
* @brief Derives the common case sensitivity for two netlists
|
|
*/
|
|
DB_PUBLIC bool combined_case_sensitive (const db::Netlist *a, const db::Netlist *b);
|
|
|
|
/**
|
|
* @brief Gets the extended net name
|
|
* This name is used for comparing the net names and also employs the pin name if one is given
|
|
*/
|
|
DB_PUBLIC const std::string &extended_net_name (const db::Net *n);
|
|
|
|
/**
|
|
* @brief Compare two nets by name
|
|
*/
|
|
DB_PUBLIC int name_compare (const db::Net *a, const db::Net *b);
|
|
|
|
/**
|
|
* @brief Returns a value indicating whether two nets are different by name
|
|
* Two unnamed nets are never different.
|
|
*/
|
|
DB_PUBLIC bool net_names_are_different (const db::Net *a, const db::Net *b);
|
|
|
|
/**
|
|
* @brief Returns a value indicating whether two nets are equal by name
|
|
* Two unnamed nets are never equal.
|
|
*/
|
|
DB_PUBLIC bool net_names_are_equal (const db::Net *a, const db::Net *b);
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// DeviceCompare definition and implementation
|
|
|
|
/**
|
|
* @brief The device compare function with "less" (operator()) and "equal" predicates
|
|
*
|
|
* Device comparison is based on the equivalence of device classes (by category) and
|
|
* in a second step, by equivalence of the devices. The device class will implement
|
|
* the device equivalence function.
|
|
*/
|
|
struct DB_PUBLIC DeviceCompare
|
|
{
|
|
bool operator() (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const;
|
|
bool equals (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// SubCircuitCompare definition and implementation
|
|
|
|
/**
|
|
* @brief The compare function for subcircuits
|
|
*
|
|
* As Subcircuits are not parametrized, the comparison of subcircuits is only based on
|
|
* the circuit equivalence (via category).
|
|
*/
|
|
struct DB_PUBLIC SubCircuitCompare
|
|
{
|
|
bool operator() (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const;
|
|
bool equals (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// CircuitPinMapper definition
|
|
|
|
/**
|
|
* @brief The Circuit pin categorizer handles swappable pin definitions per circuit
|
|
*
|
|
* Swappable pins are implemented by mapping a pin ID to an equivalent or
|
|
* effective ID which is shared by all swappable pins.
|
|
*
|
|
* This class manages swappable pins on a per-circuit basis.
|
|
*/
|
|
class DB_PUBLIC CircuitPinCategorizer
|
|
{
|
|
public:
|
|
CircuitPinCategorizer ();
|
|
|
|
void map_pins (const db::Circuit *circuit, size_t pin1_id, size_t pin2_id);
|
|
void map_pins (const db::Circuit *circuit, const std::vector<size_t> &pin_ids);
|
|
|
|
size_t is_mapped (const db::Circuit *circuit, size_t pin_id) const;
|
|
size_t normalize_pin_id (const db::Circuit *circuit, size_t pin_id) const;
|
|
|
|
private:
|
|
std::map<const db::Circuit *, tl::equivalence_clusters<size_t> > m_pin_map;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// CircuitMapper definition
|
|
|
|
/**
|
|
* @brief Handles circuit equivalence (A to B netlist)
|
|
*
|
|
* The object specifies the mapping between the circuits of
|
|
* netlist A and B and also the pin mapping between the circuits from these netlists.
|
|
*
|
|
* The "other" attribute will hold the circuit for the other netlist.
|
|
* The other methods handle pin mapping from "other" into "this" pin space.
|
|
*/
|
|
class DB_PUBLIC CircuitMapper
|
|
{
|
|
public:
|
|
CircuitMapper ();
|
|
|
|
void set_other (const db::Circuit *other)
|
|
{
|
|
mp_other = other;
|
|
}
|
|
|
|
const db::Circuit *other () const
|
|
{
|
|
return mp_other;
|
|
}
|
|
|
|
void map_pin (size_t this_pin, size_t other_pin);
|
|
bool has_other_pin_for_this_pin (size_t this_pin) const;
|
|
bool has_this_pin_for_other_pin (size_t other_pin) const;
|
|
|
|
size_t other_pin_from_this_pin (size_t this_pin) const;
|
|
size_t this_pin_from_other_pin (size_t other_pin) const;
|
|
|
|
private:
|
|
const db::Circuit *mp_other;
|
|
std::map<size_t, size_t> m_pin_map, m_rev_pin_map;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// DeviceFilter definition and implementation
|
|
|
|
/**
|
|
* @brief A device filter class
|
|
*
|
|
* This class implements a device filter which is used to skip devices when
|
|
* generating the net graph. This is useful for stripping small caps or big
|
|
* resistors.
|
|
*/
|
|
class DB_PUBLIC DeviceFilter
|
|
{
|
|
public:
|
|
DeviceFilter (double cap_threshold, double res_threshold);
|
|
|
|
bool filter (const db::Device *device) const;
|
|
|
|
private:
|
|
double m_cap_threshold, m_res_threshold;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// A generic equivalence mapper
|
|
|
|
template <class Obj>
|
|
class generic_equivalence_tracker
|
|
{
|
|
public:
|
|
generic_equivalence_tracker ()
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
bool map (const Obj *a, const Obj *b)
|
|
{
|
|
std::pair<typename std::map<const Obj *, const Obj *>::iterator, bool> inserted1 = m_eq.insert (std::make_pair (a, b));
|
|
tl_assert (inserted1.first->second == b);
|
|
std::pair<typename std::map<const Obj *, const Obj *>::iterator, bool> inserted2 = m_eq.insert (std::make_pair (b, a));
|
|
tl_assert (inserted2.first->second == a);
|
|
return inserted1.second;
|
|
}
|
|
|
|
void unmap (const Obj *a, const Obj *b)
|
|
{
|
|
m_eq.erase (a);
|
|
m_eq.erase (b);
|
|
}
|
|
|
|
const Obj *other (const Obj *o) const
|
|
{
|
|
typename std::map<const Obj *, const Obj *>::const_iterator i = m_eq.find (o);
|
|
return i == m_eq.end () ? 0 : i->second;
|
|
}
|
|
|
|
public:
|
|
std::map<const Obj *, const Obj *> m_eq;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// A class describing the equivalence between subcircuits we established so far
|
|
|
|
class SubCircuitEquivalenceTracker
|
|
: public generic_equivalence_tracker<db::SubCircuit>
|
|
{
|
|
public:
|
|
SubCircuitEquivalenceTracker () : generic_equivalence_tracker<db::SubCircuit> () { }
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// A class describing the equivalence between devices we established so far
|
|
|
|
class DeviceEquivalenceTracker
|
|
: public generic_equivalence_tracker<db::Device>
|
|
{
|
|
public:
|
|
DeviceEquivalenceTracker () : generic_equivalence_tracker<db::Device> () { }
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// generic_categorizer definition and implementation
|
|
|
|
/**
|
|
* @brief A generic categorizer
|
|
*
|
|
* The objective of this class is to supply a category ID for a given object.
|
|
* The category ID also identifies equivalent objects from netlist A and B.
|
|
*/
|
|
template <class Obj>
|
|
class DB_PUBLIC generic_categorizer
|
|
{
|
|
public:
|
|
generic_categorizer (bool with_name = true);
|
|
|
|
void set_case_sensitive (bool f);
|
|
void same (const Obj *ca, const Obj *cb);
|
|
bool has_cat_for (const Obj *cls);
|
|
size_t cat_for (const Obj *cls);
|
|
|
|
public:
|
|
std::map<const Obj *, size_t> m_cat_by_ptr;
|
|
std::map<std::string, size_t> m_cat_by_name;
|
|
size_t m_next_cat;
|
|
bool m_with_name;
|
|
bool m_case_sensitive;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// DeviceCategorizer definition and implementation
|
|
|
|
/**
|
|
* @brief A device categorizer
|
|
*
|
|
* The objective of this class is to supply a category ID for a given device class.
|
|
* The category ID also identities equivalent device classes from netlist A and B.
|
|
*/
|
|
class DB_PUBLIC DeviceCategorizer
|
|
: private generic_categorizer<db::DeviceClass>
|
|
{
|
|
public:
|
|
DeviceCategorizer ();
|
|
|
|
void same_class (const db::DeviceClass *ca, const db::DeviceClass *cb);
|
|
size_t cat_for_device (const db::Device *device);
|
|
|
|
bool has_cat_for_device_class (const db::DeviceClass *cls)
|
|
{
|
|
return generic_categorizer<db::DeviceClass>::has_cat_for (cls);
|
|
}
|
|
|
|
size_t cat_for_device_class (const db::DeviceClass *cls)
|
|
{
|
|
return generic_categorizer<db::DeviceClass>::cat_for (cls);
|
|
}
|
|
|
|
void clear_strict_device_categories ();
|
|
void set_strict_device_category (size_t cat);
|
|
bool is_strict_device_category (size_t cat) const;
|
|
|
|
void set_case_sensitive (bool f)
|
|
{
|
|
generic_categorizer::set_case_sensitive (f);
|
|
}
|
|
|
|
private:
|
|
std::set<size_t> m_strict_device_categories;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
// CircuitCategorizer definition and implementation
|
|
|
|
/**
|
|
* @brief A circuit categorizer
|
|
*
|
|
* The objective of this class is to supply a category ID for a given device circuit.
|
|
* The category ID also identities equivalent circuit from netlist A and B.
|
|
*/
|
|
class DB_PUBLIC CircuitCategorizer
|
|
: private generic_categorizer<db::Circuit>
|
|
{
|
|
public:
|
|
CircuitCategorizer ();
|
|
|
|
void same_circuit (const db::Circuit *ca, const db::Circuit *cb);
|
|
size_t cat_for_subcircuit (const db::SubCircuit *subcircuit);
|
|
|
|
size_t cat_for_circuit (const db::Circuit *cr)
|
|
{
|
|
return generic_categorizer<db::Circuit>::cat_for (cr);
|
|
}
|
|
|
|
void set_case_sensitive (bool f)
|
|
{
|
|
generic_categorizer::set_case_sensitive (f);
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|