mirror of https://github.com/KLayout/klayout.git
Netlist compare: configurable device parameter compare scheme.
This commit is contained in:
parent
43f65e4d29
commit
da5680ef24
|
|
@ -21,10 +21,81 @@
|
|||
*/
|
||||
|
||||
#include "dbDeviceClass.h"
|
||||
#include "dbDevice.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// EqualDeviceParameters implementation
|
||||
|
||||
static int compare_parameters (double pa, double pb, double absolute, double relative)
|
||||
{
|
||||
double pa_min = pa - absolute;
|
||||
double pa_max = pa + absolute;
|
||||
|
||||
double mean = 0.5 * (fabs (pa) + fabs (pb));
|
||||
pa_min -= mean * relative;
|
||||
pa_max += mean * relative;
|
||||
|
||||
// NOTE: parameter values may be small (e.g. pF for caps) -> no epsilon
|
||||
|
||||
if (pa_max < pb) {
|
||||
return -1;
|
||||
} else if (pa_min > pb) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
EqualDeviceParameters::EqualDeviceParameters ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
EqualDeviceParameters::EqualDeviceParameters (size_t parameter_id)
|
||||
{
|
||||
m_compare_set.push_back (std::make_pair (parameter_id, std::make_pair (0.0, 0.0)));
|
||||
}
|
||||
|
||||
EqualDeviceParameters::EqualDeviceParameters (size_t parameter_id, double relative, double absolute)
|
||||
{
|
||||
m_compare_set.push_back (std::make_pair (parameter_id, std::make_pair (relative, absolute)));
|
||||
}
|
||||
|
||||
bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) const
|
||||
{
|
||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = m_compare_set.begin (); c != m_compare_set.end (); ++c) {
|
||||
int cmp = compare_parameters (a.parameter_value (c->first), b.parameter_value (c->first), c->second.first, c->second.second);
|
||||
if (cmp != 0) {
|
||||
return cmp < 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EqualDeviceParameters::equal (const db::Device &a, const db::Device &b) const
|
||||
{
|
||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = m_compare_set.begin (); c != m_compare_set.end (); ++c) {
|
||||
int cmp = compare_parameters (a.parameter_value (c->first), b.parameter_value (c->first), c->second.first, c->second.second);
|
||||
if (cmp != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EqualDeviceParameters &EqualDeviceParameters::operator+= (const EqualDeviceParameters &other)
|
||||
{
|
||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = other.m_compare_set.begin (); c != other.m_compare_set.end (); ++c) {
|
||||
m_compare_set.push_back (*c);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// DeviceClass class implementation
|
||||
|
||||
|
|
@ -137,4 +208,58 @@ size_t DeviceClass::terminal_id_for_name (const std::string &name) const
|
|||
throw tl::Exception (tl::to_string (tr ("Invalid terminal name")) + ": '" + name + "'");
|
||||
}
|
||||
|
||||
bool DeviceClass::less (const db::Device &a, const db::Device &b)
|
||||
{
|
||||
tl_assert (a.device_class () != 0);
|
||||
tl_assert (b.device_class () != 0);
|
||||
|
||||
const db::DeviceParameterCompareDelegate *pcd = a.device_class ()->mp_pc_delegate.get ();
|
||||
if (! pcd) {
|
||||
pcd = b.device_class ()->mp_pc_delegate.get ();
|
||||
}
|
||||
|
||||
if (pcd != 0) {
|
||||
return pcd->less (a, b);
|
||||
} else {
|
||||
|
||||
const std::vector<db::DeviceParameterDefinition> &pd = a.device_class ()->parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
|
||||
int cmp = compare_parameters (a.parameter_value (p->id ()), b.parameter_value (p->id ()), 0.0, 0.0);
|
||||
if (cmp != 0) {
|
||||
return cmp < 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceClass::equal (const db::Device &a, const db::Device &b)
|
||||
{
|
||||
tl_assert (a.device_class () != 0);
|
||||
tl_assert (b.device_class () != 0);
|
||||
|
||||
const db::DeviceParameterCompareDelegate *pcd = a.device_class ()->mp_pc_delegate.get ();
|
||||
if (! pcd) {
|
||||
pcd = b.device_class ()->mp_pc_delegate.get ();
|
||||
}
|
||||
|
||||
if (pcd != 0) {
|
||||
return pcd->equal (a, b);
|
||||
} else {
|
||||
|
||||
const std::vector<db::DeviceParameterDefinition> &pd = a.device_class ()->parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
|
||||
int cmp = compare_parameters (a.parameter_value (p->id ()), b.parameter_value (p->id ()), 0.0, 0.0);
|
||||
if (cmp != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,6 +207,53 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A device parameter compare delegate
|
||||
*
|
||||
* Device parameter compare delegates are used to establish
|
||||
* device equivalence in the context of netlist comparison.
|
||||
*/
|
||||
class DB_PUBLIC DeviceParameterCompareDelegate
|
||||
: public gsi::ObjectBase, public tl::Object
|
||||
{
|
||||
public:
|
||||
DeviceParameterCompareDelegate () { }
|
||||
virtual ~DeviceParameterCompareDelegate () { }
|
||||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const = 0;
|
||||
virtual bool equal (const db::Device &a, const db::Device &b) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A parameter compare delegate that compares several parameters either relative or absolute (or both)
|
||||
*
|
||||
* The reasoning behind this class is to supply a chainable compare delegate: ab = a + b
|
||||
* where a and b are compare delegates for two different parameters and ab is the combined compare delegate.
|
||||
*/
|
||||
class DB_PUBLIC EqualDeviceParameters
|
||||
: public DeviceParameterCompareDelegate
|
||||
{
|
||||
public:
|
||||
EqualDeviceParameters ();
|
||||
EqualDeviceParameters (size_t parameter_id);
|
||||
EqualDeviceParameters (size_t parameter_id, double relative, double absolute);
|
||||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
virtual bool equal (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
EqualDeviceParameters &operator+= (const EqualDeviceParameters &other);
|
||||
|
||||
EqualDeviceParameters operator+ (const EqualDeviceParameters &other) const
|
||||
{
|
||||
EqualDeviceParameters pc (*this);
|
||||
pc += other;
|
||||
return pc;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<size_t, std::pair<double, double> > > m_compare_set;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A device class
|
||||
*
|
||||
|
|
@ -228,14 +275,14 @@ public:
|
|||
/**
|
||||
* @brief Copy constructor
|
||||
* NOTE: do not use this copy constructor as the device class
|
||||
* is intended to subclassing.
|
||||
* is intended for subclassing.
|
||||
*/
|
||||
DeviceClass (const DeviceClass &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
* NOTE: do not use this copy constructor as the device class
|
||||
* is intended to subclassing.
|
||||
* is intended for subclassing.
|
||||
*/
|
||||
DeviceClass &operator= (const DeviceClass &other);
|
||||
|
||||
|
|
@ -365,7 +412,7 @@ public:
|
|||
size_t terminal_id_for_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Clears the circuit
|
||||
* @brief Clones the device class
|
||||
*/
|
||||
virtual DeviceClass *clone () const
|
||||
{
|
||||
|
|
@ -414,6 +461,46 @@ public:
|
|||
return tid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares the parameters of the devices a and b
|
||||
*
|
||||
* a and b are expected to originate from this or an equivalent device class having
|
||||
* the same parameters.
|
||||
* This is the "less" operation. If a parameter compare delegate is registered, this
|
||||
* compare request will be forwarded to the delegate.
|
||||
*
|
||||
* If two devices with different device classes are compared and only one of
|
||||
* the classes features a delegate, the one with the delegate is employed.
|
||||
*/
|
||||
static bool less (const db::Device &a, const db::Device &b);
|
||||
|
||||
/**
|
||||
* @brief Compares the parameters of the devices a and b
|
||||
*
|
||||
* a and b are expected to originate from this or an equivalent device class having
|
||||
* the same parameters.
|
||||
* This is the "equal" operation. If a parameter compare delegate is registered, this
|
||||
* compare request will be forwarded to the delegate.
|
||||
*
|
||||
* If two devices with different device classes are compared and only one of
|
||||
* the classes features a delegate, the one with the delegate is employed.
|
||||
*/
|
||||
static bool equal (const db::Device &a, const db::Device &b);
|
||||
|
||||
/**
|
||||
* @brief Registers a compare delegate
|
||||
*
|
||||
* The reasoning behind chosing a delegate is that a delegate is efficient
|
||||
* also in scripts if one of the standard delegates is taken.
|
||||
*
|
||||
* The device class takes ownership of the delegate.
|
||||
*/
|
||||
virtual void set_parameter_compare_delegate (db::DeviceParameterCompareDelegate *delegate)
|
||||
{
|
||||
delegate->keep (); // assume transfer of ownership for scripts
|
||||
mp_pc_delegate.reset (delegate);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Netlist;
|
||||
|
||||
|
|
@ -421,6 +508,7 @@ private:
|
|||
std::vector<DeviceTerminalDefinition> m_terminal_definitions;
|
||||
std::vector<DeviceParameterDefinition> m_parameter_definitions;
|
||||
db::Netlist *mp_netlist;
|
||||
tl::shared_ptr<db::DeviceParameterCompareDelegate> mp_pc_delegate;
|
||||
|
||||
void set_netlist (db::Netlist *nl)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,16 +40,7 @@ struct DeviceCompare
|
|||
if (d1.second != d2.second) {
|
||||
return d1.second < d2.second;
|
||||
}
|
||||
|
||||
const std::vector<db::DeviceParameterDefinition> &dp = d1.first->device_class ()->parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = dp.begin (); i != dp.end (); ++i) {
|
||||
double v1 = d1.first->parameter_value (i->id ());
|
||||
double v2 = d2.first->parameter_value (i->id ());
|
||||
if (fabs (v1 - v2) > db::epsilon) {
|
||||
return v1 < v2;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return db::DeviceClass::less (*d1.first, *d2.first);
|
||||
}
|
||||
|
||||
bool equals (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const
|
||||
|
|
@ -57,16 +48,7 @@ struct DeviceCompare
|
|||
if (d1.second != d2.second) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<db::DeviceParameterDefinition> &dp = d1.first->device_class ()->parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = dp.begin (); i != dp.end (); ++i) {
|
||||
double v1 = d1.first->parameter_value (i->id ());
|
||||
double v2 = d2.first->parameter_value (i->id ());
|
||||
if (fabs (v1 - v2) > db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return db::DeviceClass::equal (*d1.first, *d2.first);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1419,6 +1401,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
good = false;
|
||||
} else {
|
||||
if (mp_logger) {
|
||||
dc.equals (dm->second, std::make_pair (d.operator-> (), device_cat)); // @@@
|
||||
mp_logger->match_devices_with_different_parameters (dm->second.first, d.operator-> ());
|
||||
}
|
||||
good = false;
|
||||
|
|
|
|||
|
|
@ -473,11 +473,120 @@ Class<db::DeviceParameterDefinition> decl_dbDeviceParameterDefinition ("db", "De
|
|||
"This class has been added in version 0.26."
|
||||
);
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A DeviceParameterCompare implementation that allows reimplementation of the virtual methods
|
||||
*/
|
||||
class GenericDeviceParameterCompare
|
||||
: public db::EqualDeviceParameters
|
||||
{
|
||||
public:
|
||||
GenericDeviceParameterCompare ()
|
||||
: db::EqualDeviceParameters ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const
|
||||
{
|
||||
if (cb_less.can_issue ()) {
|
||||
return cb_less.issue<db::EqualDeviceParameters, bool, const db::Device &, const db::Device &> (&db::EqualDeviceParameters::less, a, b);
|
||||
} else {
|
||||
return db::EqualDeviceParameters::less (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool equal (const db::Device &a, const db::Device &b) const
|
||||
{
|
||||
if (cb_equal.can_issue ()) {
|
||||
return cb_equal.issue<db::EqualDeviceParameters, bool, const db::Device &, const db::Device &> (&db::EqualDeviceParameters::equal, a, b);
|
||||
} else {
|
||||
return db::EqualDeviceParameters::equal (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
gsi::Callback cb_less, cb_equal;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
db::EqualDeviceParameters *make_equal_dp (size_t param_id, double absolute, double relative)
|
||||
{
|
||||
return new db::EqualDeviceParameters (param_id, absolute, relative);
|
||||
}
|
||||
|
||||
Class<db::EqualDeviceParameters> decl_dbEqualDeviceParameters ("db", "EqualDeviceParameters",
|
||||
gsi::constructor ("new", &make_equal_dp, gsi::arg ("param_id"), gsi::arg ("absolute", 0.0), gsi::arg ("relative", 0.0),
|
||||
"@brief Creates a device parameter comparer for a single parameter.\n"
|
||||
"'absolute' is the absolute deviation allowed for the parameter values. "
|
||||
"'relative' is the relative deviation allowed for the parameter values (a value between 0 and 1).\n"
|
||||
"\n"
|
||||
"A value of 0 for both absolute and relative deviation means the parameters have to match exactly.\n"
|
||||
"\n"
|
||||
"If 'absolute' and 'relative' are both given, their deviations will add to the allowed difference between "
|
||||
"two parameter values. The relative deviation will be applied to the mean value of both parameter values. "
|
||||
"For example, when comparing parameter values of 40 and 60, a relative deviation of 0.35 means an absolute "
|
||||
"deviation of 17.5 (= 0.35 * average of 40 and 60) which does not make both values match."
|
||||
) +
|
||||
gsi::method ("+", &db::EqualDeviceParameters::operator+, gsi::arg ("other"),
|
||||
"@brief Combines two parameters for comparison.\n"
|
||||
"The '+' operator will join the parameter comparers and produce one that checks the combined parameters.\n"
|
||||
) +
|
||||
gsi::method ("+=", &db::EqualDeviceParameters::operator+, gsi::arg ("other"),
|
||||
"@brief Combines two parameters for comparison (in-place).\n"
|
||||
"The '+=' operator will join the parameter comparers and produce one that checks the combined parameters.\n"
|
||||
),
|
||||
"@brief A device parameter equality comparer.\n"
|
||||
"Attach this object to a device class with \\DeviceClass#equal_parameters= to make the device "
|
||||
"class use this comparer:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# 20nm tolerance for length:\n"
|
||||
"equal_device_parameters = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS4Transistor::PARAM_L, 0.02, 0.0)\n"
|
||||
"# one percent tolerance for width:\n"
|
||||
"equal_device_parameters += RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS4Transistor::PARAM_W, 0.0, 0.01)\n"
|
||||
"# applies the compare delegate:\n"
|
||||
"netlist.device_class_by_name(\"NMOS\").equal_parameters = equal_device_parameters\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"You can use this class to specify fuzzy equality criteria for the comparison of device parameters in "
|
||||
"netlist verification or to confine the equality of devices to certain parameters only.\n"
|
||||
"\n"
|
||||
"This class has been added in version 0.26."
|
||||
);
|
||||
|
||||
Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_dbEqualDeviceParameters, "db", "GenericDeviceParameterCompare",
|
||||
gsi::callback ("equal", &GenericDeviceParameterCompare::equal, &GenericDeviceParameterCompare::cb_equal, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
||||
"@brief Compares the parameters of two devices for equality. "
|
||||
"Returns true, if the parameters of device a and b are considered equal."
|
||||
) +
|
||||
gsi::callback ("less", &GenericDeviceParameterCompare::less, &GenericDeviceParameterCompare::cb_less, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
||||
"@brief Compares the parameters of two devices for a begin less than b. "
|
||||
"Returns true, if the parameters of device a are considered less than those of device b."
|
||||
),
|
||||
"@brief A class implementing the comparison of device parameters.\n"
|
||||
"Reimplement this class to provide a custom device parameter compare scheme.\n"
|
||||
"Attach this object to a device class with \\DeviceClass#equal_parameters= to make the device "
|
||||
"class use this comparer.\n"
|
||||
"\n"
|
||||
"This class is intended for special cases. In most scenarios it is easier to use \\EqualDeviceParameters instead of "
|
||||
"implementing a custom comparer class.\n"
|
||||
"\n"
|
||||
"This class has been added in version 0.26."
|
||||
);
|
||||
|
||||
static tl::id_type id_of_device_class (const db::DeviceClass *cls)
|
||||
{
|
||||
return tl::id_of (cls);
|
||||
}
|
||||
|
||||
static void equal_parameters (db::DeviceClass *cls, db::EqualDeviceParameters *comparer)
|
||||
{
|
||||
cls->set_parameter_compare_delegate (comparer);
|
||||
}
|
||||
|
||||
Class<db::DeviceClass> decl_dbDeviceClass ("db", "DeviceClass",
|
||||
gsi::method ("name", &db::DeviceClass::name,
|
||||
"@brief Gets the name of the device class."
|
||||
|
|
@ -533,6 +642,15 @@ Class<db::DeviceClass> decl_dbDeviceClass ("db", "DeviceClass",
|
|||
"@brief Returns the terminal ID of the terminal with the given name.\n"
|
||||
"An exception is thrown if there is no terminal with the given name. Use \\has_terminal to check "
|
||||
"whether the name is a valid terminal name."
|
||||
) +
|
||||
gsi::method_ext ("equal_parameters=", &equal_parameters, gsi::arg ("comparer"),
|
||||
"@brief Specifies a device parameter comparer for netlist verification.\n"
|
||||
"By default, all devices are compared with all parameters. If you want to select only certain parameters "
|
||||
"for comparison or use a fuzzy compare criterion, use an \\EqualDeviceParameters object and assign it "
|
||||
"to the device class of one netlist. You can also chain multiple \\EqualDeviceParameters objects with the '+' operator "
|
||||
"for specifying multiple parameters in the equality check.\n"
|
||||
"\n"
|
||||
"In special cases, you can even implement a custom compare scheme by deriving your own comparer from the \\GenericDeviceParameterCompare class."
|
||||
),
|
||||
"@brief A class describing a specific type of device.\n"
|
||||
"Device class objects live in the context of a \\Netlist object. After a "
|
||||
|
|
@ -1231,14 +1349,14 @@ Class<db::NetlistSpiceWriter> db_NetlistSpiceWriter (db_NetlistWriter, "db", "Ne
|
|||
"@code\n"
|
||||
"writer = RBA::NetlistSpiceWriter::new\n"
|
||||
"netlist.write(path, writer)\n"
|
||||
"@endcode\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"You can give a custom description for the headline:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"writer = RBA::NetlistSpiceWriter::new\n"
|
||||
"netlist.write(path, writer, \"A custom description\")\n"
|
||||
"@endcode\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"To customize the output, you can use a device writer delegate.\n"
|
||||
"The delegate is an object of a class derived from \\NetlistSpiceWriterDelegate which "
|
||||
|
|
@ -1279,7 +1397,7 @@ Class<db::NetlistSpiceWriter> db_NetlistSpiceWriter (db_NetlistWriter, "db", "Ne
|
|||
"# write the netlist with delegate:\n"
|
||||
"writer = RBA::NetlistSpiceWriter::new(MyDelegate::new)\n"
|
||||
"netlist.write(path, writer)\n"
|
||||
"@endcode\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.26."
|
||||
);
|
||||
|
|
@ -1305,7 +1423,7 @@ Class<db::NetlistSpiceReader> db_NetlistSpiceReader (db_NetlistReader, "db", "Ne
|
|||
"writer = RBA::NetlistSpiceReader::new\n"
|
||||
"netlist = RBA::Netlist::new\n"
|
||||
"netlist.read(path, reader)\n"
|
||||
"@endcode\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.26."
|
||||
);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace {
|
|||
* @brief A NetlistDeviceExtractor implementation that allows reimplementation of the virtual methods
|
||||
*/
|
||||
class GenericNetlistCompareLogger
|
||||
: public db::NetlistCompareLogger
|
||||
: public gsi::ObjectBase, public db::NetlistCompareLogger
|
||||
{
|
||||
public:
|
||||
GenericNetlistCompareLogger ()
|
||||
|
|
@ -296,6 +296,7 @@ public:
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
|
|
@ -340,11 +341,13 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger ("db", "Gene
|
|||
gsi::callback ("match_nets", &GenericNetlistCompareLogger::match_nets, &GenericNetlistCompareLogger::cb_match_nets, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This function is called when two nets are identified.\n"
|
||||
"If two nets are identified as a corresponding pair, this method will be called with both nets.\n"
|
||||
"If the nets can be paired, but this match is ambiguous, \\match_ambiguous_nets_fb will be called instead.\n"
|
||||
"If the nets can be paired, but this match is ambiguous, \\match_ambiguous_nets will be called instead.\n"
|
||||
"If nets can't be matched to a partner, \\net_mismatch will be called.\n"
|
||||
) +
|
||||
gsi::callback ("match_ambiguous_nets", &GenericNetlistCompareLogger::match_ambiguous_nets, &GenericNetlistCompareLogger::cb_match_ambiguous_nets, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This function is called when two nets are identified, but this choice is ambiguous.\n"
|
||||
"This choice is a last-resort fallback to allow continuation of the compare procedure. It is likely that this "
|
||||
"compare will fail later. Looking for ambiguous nets allows deduction of the origin of this faulty decision. "
|
||||
"See \\match_nets for more details."
|
||||
) +
|
||||
gsi::callback ("net_mismatch", &GenericNetlistCompareLogger::net_mismatch, &GenericNetlistCompareLogger::cb_net_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
|
|
@ -369,7 +372,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger ("db", "Gene
|
|||
) +
|
||||
gsi::callback ("device_mismatch", &GenericNetlistCompareLogger::device_mismatch, &GenericNetlistCompareLogger::cb_device_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This function is called when two devices can't be paired.\n"
|
||||
"This will report the device considered in a or b. The other argument is nil."
|
||||
"This will report the device considered in a or b. The other argument is nil. "
|
||||
"See \\match_devices for details.\n"
|
||||
) +
|
||||
gsi::callback ("match_pins", &GenericNetlistCompareLogger::match_pins, &GenericNetlistCompareLogger::cb_match_pins, gsi::arg ("a"), gsi::arg ("b"),
|
||||
|
|
@ -379,7 +382,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger ("db", "Gene
|
|||
) +
|
||||
gsi::callback ("pin_mismatch", &GenericNetlistCompareLogger::pin_mismatch, &GenericNetlistCompareLogger::cb_pin_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This function is called when two pins can't be paired.\n"
|
||||
"This will report the pin considered in a or b. The other argument is nil."
|
||||
"This will report the pin considered in a or b. The other argument is nil. "
|
||||
"See \\match_pins for details.\n"
|
||||
) +
|
||||
gsi::callback ("match_subcircuits", &GenericNetlistCompareLogger::match_subcircuits, &GenericNetlistCompareLogger::cb_match_subcircuits, gsi::arg ("a"), gsi::arg ("b"),
|
||||
|
|
@ -389,7 +392,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger ("db", "Gene
|
|||
) +
|
||||
gsi::callback ("subcircuit_mismatch", &GenericNetlistCompareLogger::subcircuit_mismatch, &GenericNetlistCompareLogger::cb_subcircuit_mismatch, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This function is called when two subcircuits can't be paired.\n"
|
||||
"This will report the subcircuit considered in a or b. The other argument is nil."
|
||||
"This will report the subcircuit considered in a or b. The other argument is nil. "
|
||||
"See \\match_subcircuits for details.\n"
|
||||
),
|
||||
"@brief An event receiver for the netlist compare feature.\n"
|
||||
|
|
@ -400,19 +403,28 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger ("db", "Gene
|
|||
"This class has been introduced in version 0.26.\n"
|
||||
);
|
||||
|
||||
static db::NetlistComparer *make_comparer (GenericNetlistCompareLogger *logger)
|
||||
static db::NetlistComparer *make_comparer0 ()
|
||||
{
|
||||
return new db::NetlistComparer (0);
|
||||
}
|
||||
|
||||
static db::NetlistComparer *make_comparer1 (GenericNetlistCompareLogger *logger)
|
||||
{
|
||||
return new db::NetlistComparer (logger);
|
||||
}
|
||||
|
||||
Class<db::NetlistComparer> decl_dbNetlistComparer ("db", "NetlistComparer",
|
||||
gsi::constructor ("new", &make_comparer, gsi::arg ("logger", (GenericNetlistCompareLogger *) 0),
|
||||
"@brief Creates a new comparer object."
|
||||
gsi::constructor ("new", &make_comparer0,
|
||||
"@brief Creates a new comparer object.\n"
|
||||
"See the class description for more details."
|
||||
) +
|
||||
gsi::constructor ("new", &make_comparer1, gsi::arg ("logger"),
|
||||
"@brief Creates a new comparer object.\n"
|
||||
"The logger is a delegate or event receiver which the comparer will send compare events to. "
|
||||
"See the class description for more details."
|
||||
) +
|
||||
gsi::method ("same_nets", &db::NetlistComparer::same_nets, gsi::arg ("net_a"), gsi::arg ("net_b"),
|
||||
"@brief Marks two nets as identical\n"
|
||||
"@brief Marks two nets as identical.\n"
|
||||
"This makes a net net_a in netlist a identical to the corresponding\n"
|
||||
"net net_b in netlist b (see \\compare).\n"
|
||||
"Otherwise, the algorithm will try to identify nets according to their topology. "
|
||||
|
|
@ -420,43 +432,46 @@ Class<db::NetlistComparer> decl_dbNetlistComparer ("db", "NetlistComparer",
|
|||
"these hints to derive further identities."
|
||||
) +
|
||||
gsi::method ("equivalent_pins", (void (db::NetlistComparer::*) (const db::Circuit *, size_t, size_t)) &db::NetlistComparer::equivalent_pins, gsi::arg ("circuit_b"), gsi::arg ("pin_id1"), gsi::arg ("pin_id2"),
|
||||
"@brief Marks two pins of the given circuit as equivalent (i.e. they can be swapped)\n"
|
||||
"@brief Marks two pins of the given circuit as equivalent (i.e. they can be swapped).\n"
|
||||
"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."
|
||||
) +
|
||||
gsi::method ("equivalent_pins", (void (db::NetlistComparer::*) (const db::Circuit *, const std::vector<size_t> &)) &db::NetlistComparer::equivalent_pins, gsi::arg ("circuit_b"), gsi::arg ("pin_ids"),
|
||||
"@brief Marks several pins of the given circuit as equivalent (i.e. they can be swapped)\n"
|
||||
"@brief Marks several pins of the given circuit as equivalent (i.e. they can be swapped).\n"
|
||||
"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. "
|
||||
"This version is a generic variant of the two-pin version of this method."
|
||||
) +
|
||||
gsi::method ("same_device_classes", &db::NetlistComparer::same_device_classes, gsi::arg ("dev_cls_a"), gsi::arg ("dev_cls_b"),
|
||||
"@brief Marks two device classes as identical\n"
|
||||
"@brief Marks two device classes as identical.\n"
|
||||
"This makes a device class dev_cls_a in netlist a identical to the corresponding\n"
|
||||
"device class dev_cls_b in netlist b (see \\compare).\n"
|
||||
"By default device classes with the same name are identical.\n"
|
||||
) +
|
||||
gsi::method ("same_circuits", &db::NetlistComparer::same_circuits, gsi::arg ("circuit_a"), gsi::arg ("circuit_b"),
|
||||
"@brief Marks two circuits as identical\n"
|
||||
"This method makes a circuit circuit_a in netlist a identical to the corresponding\n"
|
||||
"circuit circuit_b in netlist b (see \\compare). By default circuits with the same name are identical.\n"
|
||||
"@brief Marks two circuits as identical.\n"
|
||||
"This method makes a circuit circuit_a in netlist a identical to the corresponding\n"
|
||||
"circuit circuit_b in netlist b (see \\compare). By default circuits with the same name are identical.\n"
|
||||
) +
|
||||
gsi::method ("compare", &db::NetlistComparer::compare, gsi::arg ("netlist_a"), gsi::arg ("netlist_b"),
|
||||
"@brief Compares two netlists\n"
|
||||
"@brief Compares two netlists.\n"
|
||||
"This method will perform the actual netlist compare. It will return true if both netlists are identical. "
|
||||
"If the comparer has been configured with \\same_nets or similar methods, the objects given there must "
|
||||
"be located inside 'circuit_a' and 'circuit_b' respectively."
|
||||
),
|
||||
"@brief Compares two netlists\n"
|
||||
"This class performs the actual comparison of two netlists.\n"
|
||||
"It can be used with an event receiver to log the errors and net mismatches. "
|
||||
"This class performs a comparison of two netlists.\n"
|
||||
"It can be used with an event receiver (logger) to track the errors and net mismatches. "
|
||||
"Event receivers are derived from class \\GenericNetlistCompareLogger."
|
||||
"\n"
|
||||
"The netlist comparer can be configured in different ways. Specifically hints can be given for nets, device classes or circuits. "
|
||||
"Equivalence hints can be given with \\same_nets, \\same_circuits etc.\n"
|
||||
"The netlist comparer can be configured in different ways. Specific hints can be given for nets, device classes or circuits "
|
||||
"to improve efficiency and reliability of the graph equivalence deduction algorithm. "
|
||||
"For example, objects can be marked as equivalent using \\same_nets, \\same_circuits etc. "
|
||||
"The compare algorithm will then use these hints to derive further equivalences. This way, "
|
||||
"ambiguities can be resolved.\n"
|
||||
"\n"
|
||||
"Another configuration relates to swappable pins of subcircuits. If pins marked this way, the compare algorithm may swap them to "
|
||||
"Another configuration option relates to swappable pins of subcircuits. If pins are marked this way, the compare algorithm may swap them to "
|
||||
"achieve net matching. Swappable pins belong to an 'equivalence group' and can be defined with \\equivalent_pins.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.26."
|
||||
|
|
|
|||
|
|
@ -199,6 +199,106 @@ static void prep_nl (db::Netlist &nl, const char *str)
|
|||
nl.from_string (str);
|
||||
}
|
||||
|
||||
TEST(0_EqualDeviceParameters)
|
||||
{
|
||||
db::DeviceClassMOS3Transistor dc;
|
||||
|
||||
db::EqualDeviceParameters *eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.0);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
db::Device d1 (&dc);
|
||||
db::Device d2 (&dc);
|
||||
|
||||
d1.set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 40.0);
|
||||
d2.set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 40.0);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), true);
|
||||
EXPECT_EQ (dc.equal (d2, d1), true);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
d2.set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 41.0);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), false);
|
||||
EXPECT_EQ (dc.equal (d2, d1), false);
|
||||
EXPECT_EQ (dc.less (d1, d2), true);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.9, 0.0);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), false);
|
||||
EXPECT_EQ (dc.equal (d2, d1), false);
|
||||
EXPECT_EQ (dc.less (d1, d2), true);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.0, 0.0);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), true);
|
||||
EXPECT_EQ (dc.equal (d2, d1), true);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.1, 0.0);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), true);
|
||||
EXPECT_EQ (dc.equal (d2, d1), true);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.5, 0.01);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), false);
|
||||
EXPECT_EQ (dc.equal (d2, d1), false);
|
||||
EXPECT_EQ (dc.less (d1, d2), true);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.5, 0.013);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), true);
|
||||
EXPECT_EQ (dc.equal (d2, d1), true);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
d1.set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.5);
|
||||
d2.set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.2);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), true);
|
||||
EXPECT_EQ (dc.equal (d2, d1), true);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.5, 0.013);
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), false);
|
||||
EXPECT_EQ (dc.equal (d2, d1), false);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), true);
|
||||
|
||||
eqp = new db::EqualDeviceParameters ();
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.5, 0.013);
|
||||
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W, 0.3, 1e-6);
|
||||
dc.set_parameter_compare_delegate (eqp);
|
||||
|
||||
EXPECT_EQ (dc.equal (d1, d2), true);
|
||||
EXPECT_EQ (dc.equal (d2, d1), true);
|
||||
EXPECT_EQ (dc.less (d1, d2), false);
|
||||
EXPECT_EQ (dc.less (d2, d1), false);
|
||||
}
|
||||
|
||||
TEST(1_SimpleInverter)
|
||||
{
|
||||
const char *nls1 =
|
||||
|
|
@ -496,6 +596,164 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
"end_circuit BUF BUF NOMATCH"
|
||||
);
|
||||
EXPECT_EQ (good, false);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.5, 0.0));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_ambiguous_nets INT $10\n"
|
||||
"match_ambiguous_nets INT2 $11\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"end_circuit BUF BUF MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.0));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_ambiguous_nets INT $10\n"
|
||||
"match_nets INT2 $11\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices_with_different_parameters $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"end_circuit BUF BUF NOMATCH"
|
||||
);
|
||||
EXPECT_EQ (good, false);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.2));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_ambiguous_nets INT $10\n"
|
||||
"match_nets INT2 $11\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices_with_different_parameters $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"end_circuit BUF BUF NOMATCH"
|
||||
);
|
||||
EXPECT_EQ (good, false);
|
||||
|
||||
logger.clear ();
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.0, 0.4));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_ambiguous_nets INT $10\n"
|
||||
"match_ambiguous_nets INT2 $11\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"end_circuit BUF BUF MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
logger.clear ();
|
||||
db::EqualDeviceParameters eq_dp = db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W) + db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 0.2, 0.0);
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (eq_dp));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_ambiguous_nets INT $10\n"
|
||||
"match_ambiguous_nets INT2 $11\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"end_circuit BUF BUF MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
logger.clear ();
|
||||
eq_dp = db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W) + db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L);
|
||||
nl2.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (eq_dp));
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_ambiguous_nets INT $10\n"
|
||||
"match_nets INT2 $11\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices_with_different_parameters $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"end_circuit BUF BUF NOMATCH"
|
||||
);
|
||||
EXPECT_EQ (good, false);
|
||||
}
|
||||
|
||||
TEST(5_BufferTwoPathsDifferentDeviceClasses)
|
||||
|
|
|
|||
|
|
@ -448,6 +448,92 @@ END
|
|||
|
||||
assert_equal(good, false)
|
||||
|
||||
logger.clear
|
||||
eqp = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_L, 0.2, 0.0)
|
||||
nl2.device_class_by_name("NMOS").equal_parameters = eqp
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_ambiguous_nets INT $10
|
||||
match_ambiguous_nets INT2 $11
|
||||
match_pins $0 $1
|
||||
match_pins $1 $3
|
||||
match_pins $2 $0
|
||||
match_pins $3 $2
|
||||
match_devices $1 $1
|
||||
match_devices $3 $2
|
||||
match_devices $5 $3
|
||||
match_devices $7 $4
|
||||
match_devices $2 $5
|
||||
match_devices $4 $6
|
||||
match_devices $6 $7
|
||||
match_devices $8 $8
|
||||
end_circuit BUF BUF MATCH
|
||||
END
|
||||
|
||||
assert_equal(good, true)
|
||||
|
||||
logger.clear
|
||||
eqp = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_W, 0.01, 0.0)
|
||||
eqp = eqp + RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_L, 0.2, 0.0)
|
||||
nl2.device_class_by_name("NMOS").equal_parameters = eqp
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_ambiguous_nets INT $10
|
||||
match_ambiguous_nets INT2 $11
|
||||
match_pins $0 $1
|
||||
match_pins $1 $3
|
||||
match_pins $2 $0
|
||||
match_pins $3 $2
|
||||
match_devices $1 $1
|
||||
match_devices $3 $2
|
||||
match_devices $5 $3
|
||||
match_devices $7 $4
|
||||
match_devices $2 $5
|
||||
match_devices $4 $6
|
||||
match_devices $6 $7
|
||||
match_devices $8 $8
|
||||
end_circuit BUF BUF MATCH
|
||||
END
|
||||
|
||||
assert_equal(good, true)
|
||||
|
||||
logger.clear
|
||||
eqp = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_W, 0.01, 0.0)
|
||||
eqp += RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_L, 0.2, 0.0)
|
||||
nl2.device_class_by_name("NMOS").equal_parameters = eqp
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_ambiguous_nets INT $10
|
||||
match_ambiguous_nets INT2 $11
|
||||
match_pins $0 $1
|
||||
match_pins $1 $3
|
||||
match_pins $2 $0
|
||||
match_pins $3 $2
|
||||
match_devices $1 $1
|
||||
match_devices $3 $2
|
||||
match_devices $5 $3
|
||||
match_devices $7 $4
|
||||
match_devices $2 $5
|
||||
match_devices $4 $6
|
||||
match_devices $6 $7
|
||||
match_devices $8 $8
|
||||
end_circuit BUF BUF MATCH
|
||||
END
|
||||
|
||||
assert_equal(good, true)
|
||||
|
||||
end
|
||||
|
||||
def test_6
|
||||
|
|
@ -735,6 +821,50 @@ match_pins $4 $4
|
|||
match_subcircuits $2 $1
|
||||
match_subcircuits $1 $2
|
||||
end_circuit TOP TOP MATCH
|
||||
END
|
||||
|
||||
assert_equal(good, true)
|
||||
|
||||
logger.clear
|
||||
comp = RBA::NetlistComparer::new(logger)
|
||||
|
||||
comp.equivalent_pins(nl2.circuit_by_name("NAND"), [ 1, 0 ])
|
||||
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit NAND NAND
|
||||
match_nets VSS VSS
|
||||
match_nets VDD VDD
|
||||
match_nets B B
|
||||
match_nets OUT OUT
|
||||
match_nets A A
|
||||
match_nets INT INT
|
||||
match_pins $0 $0
|
||||
match_pins $1 $1
|
||||
match_pins $2 $2
|
||||
match_pins $3 $3
|
||||
match_pins $4 $4
|
||||
match_devices $1 $1
|
||||
match_devices $2 $2
|
||||
match_devices $3 $3
|
||||
match_devices $4 $4
|
||||
end_circuit NAND NAND MATCH
|
||||
begin_circuit TOP TOP
|
||||
match_nets OUT OUT
|
||||
match_nets IN2 IN2
|
||||
match_nets VSS VSS
|
||||
match_nets VDD VDD
|
||||
match_nets IN1 IN1
|
||||
match_nets INT INT
|
||||
match_pins $0 $0
|
||||
match_pins $1 $1
|
||||
match_pins $2 $2
|
||||
match_pins $3 $3
|
||||
match_pins $4 $4
|
||||
match_subcircuits $2 $1
|
||||
match_subcircuits $1 $2
|
||||
end_circuit TOP TOP MATCH
|
||||
END
|
||||
|
||||
assert_equal(good, true)
|
||||
|
|
|
|||
Loading…
Reference in New Issue