mirror of https://github.com/KLayout/klayout.git
292 lines
8.9 KiB
C++
292 lines
8.9 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2019 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_dbNetlistCompare
|
|
#define _HDR_dbNetlistCompare
|
|
|
|
#include "dbCommon.h"
|
|
#include "dbNetlist.h"
|
|
|
|
#include <set>
|
|
#include <map>
|
|
|
|
namespace db
|
|
{
|
|
|
|
class CircuitPinMapper;
|
|
class DeviceCategorizer;
|
|
class CircuitCategorizer;
|
|
class CircuitMapper;
|
|
|
|
/**
|
|
* @brief A receiver for netlist compare events
|
|
*/
|
|
class DB_PUBLIC NetlistCompareLogger
|
|
{
|
|
public:
|
|
NetlistCompareLogger () { }
|
|
virtual ~NetlistCompareLogger () { }
|
|
|
|
/**
|
|
* @brief Begin logging for netlist a and b
|
|
*/
|
|
virtual void begin_netlist (const db::Netlist * /*a*/, const db::Netlist * /*b*/) { }
|
|
|
|
/**
|
|
* @brief End logging for netlist a and b
|
|
*/
|
|
virtual void end_netlist (const db::Netlist * /*a*/, const db::Netlist * /*b*/) { }
|
|
|
|
/**
|
|
* @brief There is a device class mismatch
|
|
* "a" is null if there is no match for b and vice versa.
|
|
*/
|
|
virtual void device_class_mismatch (const db::DeviceClass * /*a*/, const db::DeviceClass * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Begin logging for circuit a and b
|
|
*/
|
|
virtual void begin_circuit (const db::Circuit * /*a*/, const db::Circuit * /*b*/) { }
|
|
|
|
/**
|
|
* @brief End logging for circuit a and b
|
|
*/
|
|
virtual void end_circuit (const db::Circuit * /*a*/, const db::Circuit * /*b*/, bool /*matching*/) { }
|
|
|
|
/**
|
|
* @brief Circuits are skipped
|
|
* Circuits are skipped if their subcircuits could not be matched.
|
|
*/
|
|
virtual void circuit_skipped (const db::Circuit * /*a*/, const db::Circuit * /*b*/) { }
|
|
|
|
/**
|
|
* @brief There is a circuit mismatch
|
|
* "a" is null if there is no match for b and vice versa.
|
|
*/
|
|
virtual void circuit_mismatch (const db::Circuit * /*a*/, const db::Circuit * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Nets a and b match exactly
|
|
*/
|
|
virtual void match_nets (const db::Net * /*a*/, const db::Net * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Nets a and b are matched, but are ambiguous
|
|
* Other nets might also match with a and also with b. Matching this a and b is
|
|
* an arbitrary decision.
|
|
*/
|
|
virtual void match_ambiguous_nets (const db::Net * /*a*/, const db::Net * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Net a or b doesn't match
|
|
* "a" is null if there is no match for b and vice versa.
|
|
*/
|
|
virtual void net_mismatch (const db::Net * /*a*/, const db::Net * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Devices a and b match exactly
|
|
*/
|
|
virtual void match_devices (const db::Device * /*a*/, const db::Device * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Devices a and b are matched but have different parameters
|
|
*/
|
|
virtual void match_devices_with_different_parameters (const db::Device * /*a*/, const db::Device * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Devices a and b are matched but have different device classes
|
|
*/
|
|
virtual void match_devices_with_different_device_classes (const db::Device * /*a*/, const db::Device * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Device a or b doesn't match
|
|
* "a" is null if there is no match for b and vice versa.
|
|
*/
|
|
virtual void device_mismatch (const db::Device * /*a*/, const db::Device * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Pins a and b of the current circuit are matched
|
|
*/
|
|
virtual void match_pins (const db::Pin * /*a*/, const db::Pin * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Pin a or b doesn't match
|
|
* "a" is null if there is no match for b and vice versa.
|
|
*/
|
|
virtual void pin_mismatch (const db::Pin * /*a*/, const db::Pin * /*b*/) { }
|
|
|
|
/**
|
|
* @brief Subcircuits a and b match exactly
|
|
*/
|
|
virtual void match_subcircuits (const db::SubCircuit * /*a*/, const db::SubCircuit * /*b*/) { }
|
|
|
|
/**
|
|
* @brief SubCircuit a or b doesn't match
|
|
* "a" is null if there is no match for b and vice versa.
|
|
*/
|
|
virtual void subcircuit_mismatch (const db::SubCircuit * /*a*/, const db::SubCircuit * /*b*/) { }
|
|
};
|
|
|
|
/**
|
|
* @brief The netlist comparer
|
|
*/
|
|
class DB_PUBLIC NetlistComparer
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
NetlistComparer (NetlistCompareLogger *logger);
|
|
|
|
/**
|
|
* @brief Mark two nets as identical
|
|
*
|
|
* This makes a net na in netlist a identical to the corresponding
|
|
* net nb in netlist b.
|
|
* By default nets are not identical expect through their topology.
|
|
*/
|
|
void same_nets (const db::Net *na, const db::Net *nb);
|
|
|
|
/**
|
|
* @brief Mark two pins as equivalent (i.e. can be swapped)
|
|
*
|
|
* Only circuits from the *second* input can be given swappable pins.
|
|
* This will imply the same swappable pins on the equivalent circuit of the first input.
|
|
* To mark multiple pins as swappable, use the version that takes a list of pins.
|
|
*/
|
|
void equivalent_pins (const db::Circuit *cb, size_t pin1_id, size_t pin2_id);
|
|
|
|
/**
|
|
* @brief Mark multiple pins as equivalent (i.e. can be swapped)
|
|
*
|
|
* Only circuits from the *second* input can be given swappable pins.
|
|
* This will imply the same swappable pins on the equivalent circuit of the first input.
|
|
*/
|
|
void equivalent_pins (const db::Circuit *cb, const std::vector<size_t> &pin_ids);
|
|
|
|
/**
|
|
* @brief Mark two device classes as identical
|
|
*
|
|
* This makes a device class ca in netlist a identical to the corresponding
|
|
* device class cb in netlist b.
|
|
* By default device classes with the same name are identical.
|
|
*/
|
|
void same_device_classes (const db::DeviceClass *ca, const db::DeviceClass *cb);
|
|
|
|
/**
|
|
* @brief Mark two circuits as identical
|
|
*
|
|
* This makes a circuit ca in netlist a identical to the corresponding
|
|
* circuit cb in netlist b.
|
|
* By default circuits with the same name are identical.
|
|
*/
|
|
void same_circuits (const db::Circuit *ca, const db::Circuit *cb);
|
|
|
|
/**
|
|
* @brief Exclude caps with less than the given capacity value
|
|
*/
|
|
void exclude_caps (double threshold);
|
|
|
|
/**
|
|
* @brief Exclude resistors with more than the given resistance value
|
|
*/
|
|
void exclude_resistors (double threshold);
|
|
|
|
/**
|
|
* @brief Sets the maximum seach depth
|
|
*
|
|
* This value limits the search depth of the backtracking algorithm to the
|
|
* given number of jumps.
|
|
*/
|
|
void set_max_depth (size_t n)
|
|
{
|
|
m_max_depth = n;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the maximum search depth
|
|
*/
|
|
size_t max_depth () const
|
|
{
|
|
return m_max_depth;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the maximum branch complexity
|
|
*
|
|
* This value limits the maximum branch complexity of the backtracking algorithm.
|
|
* The complexity is the accumulated number of branch options with ambiguous
|
|
* net matches. Backtracking will stop when the maximum number of options
|
|
* has been exceeded.
|
|
* As the computational complexity is the square of the branch count,
|
|
* this value should be adjusted carefully.
|
|
*/
|
|
void set_max_branch_complexity (size_t n)
|
|
{
|
|
m_max_n_branch = n;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the maximum branch complexity
|
|
*/
|
|
size_t max_branch_complexity () const
|
|
{
|
|
return m_max_n_branch;
|
|
}
|
|
|
|
/**
|
|
* @brief Actually compares the two netlists
|
|
*/
|
|
bool compare (const db::Netlist *a, const db::Netlist *b) const;
|
|
|
|
protected:
|
|
bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector<std::pair<const Net *, const Net *> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const;
|
|
bool all_subcircuits_verified (const db::Circuit *c, const std::set<const db::Circuit *> &verified_circuits) const;
|
|
static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper);
|
|
|
|
NetlistCompareLogger *mp_logger;
|
|
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<const Net *, const Net *> > > m_same_nets;
|
|
std::auto_ptr<CircuitPinMapper> mp_circuit_pin_mapper;
|
|
std::auto_ptr<DeviceCategorizer> mp_device_categorizer;
|
|
std::auto_ptr<CircuitCategorizer> mp_circuit_categorizer;
|
|
double m_cap_threshold;
|
|
double m_res_threshold;
|
|
size_t m_max_n_branch;
|
|
size_t m_max_depth;
|
|
};
|
|
|
|
}
|
|
|
|
namespace tl
|
|
{
|
|
|
|
template<> struct type_traits<db::NetlistComparer> : public tl::type_traits<void>
|
|
{
|
|
// mark "NetlistDeviceExtractor" as having a default ctor and no copy ctor
|
|
typedef tl::false_tag has_copy_constructor;
|
|
typedef tl::false_tag has_default_constructor;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|