mirror of https://github.com/KLayout/klayout.git
Device parameter comparer now also compares other (primary) parameters, parameters primary in both netlists are considered to be compared by default, 'ignore' feature in tolerance
This commit is contained in:
parent
37457aa02f
commit
42b7290fe5
|
|
@ -30,8 +30,20 @@ namespace db
|
|||
// --------------------------------------------------------------------------------
|
||||
// EqualDeviceParameters implementation
|
||||
|
||||
static int compare_parameters (double pa, double pb, double absolute, double relative)
|
||||
// NOTE: to allow rounding errors for parameter comparison, we use
|
||||
// a default relative tolerance.
|
||||
const double default_relative_tolerance = 1e-6;
|
||||
|
||||
const double default_absolute_tolerance = 0.0;
|
||||
|
||||
|
||||
static int compare_parameters (double pa, double pb, double absolute = default_absolute_tolerance, double relative = default_relative_tolerance)
|
||||
{
|
||||
// absolute value < 0 means: ignore this parameter (= always match)
|
||||
if (absolute < 0.0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double pa_min = pa - absolute;
|
||||
double pa_max = pa + absolute;
|
||||
|
||||
|
|
@ -57,14 +69,31 @@ EqualDeviceParameters::EqualDeviceParameters ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
EqualDeviceParameters::EqualDeviceParameters (size_t parameter_id)
|
||||
EqualDeviceParameters::EqualDeviceParameters (size_t parameter_id, bool ignore)
|
||||
{
|
||||
m_compare_set.push_back (std::make_pair (parameter_id, std::make_pair (0.0, 0.0)));
|
||||
m_compare_set.push_back (std::make_pair (parameter_id, std::make_pair (ignore ? -1.0 : 0.0, 0.0)));
|
||||
}
|
||||
|
||||
EqualDeviceParameters::EqualDeviceParameters (size_t parameter_id, double relative, double absolute)
|
||||
EqualDeviceParameters::EqualDeviceParameters (size_t parameter_id, double absolute, double relative)
|
||||
{
|
||||
m_compare_set.push_back (std::make_pair (parameter_id, std::make_pair (relative, absolute)));
|
||||
m_compare_set.push_back (std::make_pair (parameter_id, std::make_pair (std::max (0.0, absolute), std::max (0.0, relative))));
|
||||
}
|
||||
|
||||
std::string EqualDeviceParameters::to_string () const
|
||||
{
|
||||
std::string res;
|
||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = m_compare_set.begin (); c != m_compare_set.end (); ++c) {
|
||||
if (!res.empty ()) {
|
||||
res += ";";
|
||||
}
|
||||
res += "#" + tl::to_string (c->first) + ":";
|
||||
if (c->second.first < 0.0) {
|
||||
res += "ignore";
|
||||
} else {
|
||||
res += "A" + tl::to_string (c->second.first) + "/R" + tl::to_string (c->second.second);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) const
|
||||
|
|
@ -76,6 +105,30 @@ bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) cons
|
|||
}
|
||||
}
|
||||
|
||||
// compare the remaining parameters with a default precision
|
||||
|
||||
std::set<size_t> seen;
|
||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = m_compare_set.begin (); c != m_compare_set.end (); ++c) {
|
||||
seen.insert (c->first);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if (seen.find (p->id ()) != seen.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const db::DeviceParameterDefinition *pdb = b.device_class ()->parameter_definition (p->id ());
|
||||
if (pdb && pdb->is_primary () && p->is_primary ()) {
|
||||
int cmp = compare_parameters (a.parameter_value (p->id ()), b.parameter_value (p->id ()));
|
||||
if (cmp != 0) {
|
||||
return cmp < 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -109,47 +162,6 @@ bool AllDeviceParametersAreEqual::less (const db::Device &a, const db::Device &b
|
|||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// PrimaryDeviceParametersAreEqual class implementation
|
||||
|
||||
class DB_PUBLIC PrimaryDeviceParametersAreEqual
|
||||
: public DeviceParameterCompareDelegate
|
||||
{
|
||||
public:
|
||||
PrimaryDeviceParametersAreEqual (double relative);
|
||||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
private:
|
||||
double m_relative;
|
||||
};
|
||||
|
||||
PrimaryDeviceParametersAreEqual::PrimaryDeviceParametersAreEqual (double relative)
|
||||
: m_relative (relative)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
bool PrimaryDeviceParametersAreEqual::less (const db::Device &a, const db::Device &b) const
|
||||
{
|
||||
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) {
|
||||
const db::DeviceParameterDefinition *pdb = b.device_class ()->parameter_definition (p->id ());
|
||||
if (! pdb) {
|
||||
continue;
|
||||
}
|
||||
if (! pdb->is_primary () && ! p->is_primary ()) {
|
||||
continue;
|
||||
}
|
||||
int cmp = compare_parameters (a.parameter_value (p->id ()), b.parameter_value (p->id ()), 0.0, m_relative);
|
||||
if (cmp != 0) {
|
||||
return cmp < 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// DeviceClass class implementation
|
||||
|
||||
|
|
@ -279,12 +291,8 @@ size_t DeviceClass::terminal_id_for_name (const std::string &name) const
|
|||
throw tl::Exception (tl::to_string (tr ("Invalid terminal name")) + ": '" + name + "'");
|
||||
}
|
||||
|
||||
// NOTE: to allow rounding errors for parameter comparison, we use
|
||||
// a default relative tolerance.
|
||||
const double relative_tolerance = 1e-6;
|
||||
|
||||
// The default compare delegate
|
||||
static PrimaryDeviceParametersAreEqual default_compare (relative_tolerance);
|
||||
static EqualDeviceParameters default_compare;
|
||||
|
||||
bool DeviceClass::less (const db::Device &a, const db::Device &b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -309,11 +309,14 @@ class DB_PUBLIC EqualDeviceParameters
|
|||
{
|
||||
public:
|
||||
EqualDeviceParameters ();
|
||||
EqualDeviceParameters (size_t parameter_id);
|
||||
EqualDeviceParameters (size_t parameter_id, bool ignore = false);
|
||||
EqualDeviceParameters (size_t parameter_id, double relative, double absolute);
|
||||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
// for test purposes
|
||||
std::string to_string () const;
|
||||
|
||||
EqualDeviceParameters &operator+= (const EqualDeviceParameters &other);
|
||||
|
||||
EqualDeviceParameters operator+ (const EqualDeviceParameters &other) const
|
||||
|
|
@ -507,6 +510,14 @@ public:
|
|||
return m_parameter_definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter definitions
|
||||
*/
|
||||
std::vector<DeviceParameterDefinition> ¶meter_definitions_non_const ()
|
||||
{
|
||||
return m_parameter_definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a parameter definition
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -908,6 +908,11 @@ db::EqualDeviceParameters *make_equal_dp (size_t param_id, double absolute, doub
|
|||
return new db::EqualDeviceParameters (param_id, absolute, relative);
|
||||
}
|
||||
|
||||
db::EqualDeviceParameters *make_ignore_dp (size_t param_id)
|
||||
{
|
||||
return new db::EqualDeviceParameters (param_id, true);
|
||||
}
|
||||
|
||||
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"
|
||||
|
|
@ -921,6 +926,15 @@ Class<db::EqualDeviceParameters> decl_dbEqualDeviceParameters ("db", "EqualDevic
|
|||
"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::constructor ("ignore", &make_ignore_dp, gsi::arg ("param_id"),
|
||||
"@brief Creates a device parameter comparer which ignores the parameter.\n"
|
||||
"\n"
|
||||
"This specification can be used to make a parameter ignored. Starting with version 0.27.4, all primary parameters "
|
||||
"are compared. Before 0.27.4, giving a tolerance meant only those parameters are compared. To exclude a primary "
|
||||
"parameter from the compare, use the 'ignore' specification for that parameter.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.27.4.\n"
|
||||
) +
|
||||
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"
|
||||
|
|
@ -928,7 +942,8 @@ Class<db::EqualDeviceParameters> decl_dbEqualDeviceParameters ("db", "EqualDevic
|
|||
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"
|
||||
),
|
||||
) +
|
||||
gsi::method ("to_string", &db::EqualDeviceParameters::to_string, "@hide"),
|
||||
"@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"
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,19 @@ END
|
|||
|
||||
end
|
||||
|
||||
def test_15_deviceParameterCompare
|
||||
|
||||
dpc = RBA::EqualDeviceParameters::new(1)
|
||||
assert_equal(dpc.to_string, "#1:A0/R0")
|
||||
|
||||
dpc += RBA::EqualDeviceParameters::new(2, 1.0, 0.25)
|
||||
assert_equal(dpc.to_string, "#1:A0/R0;#2:A1/R0.25")
|
||||
|
||||
dpc += RBA::EqualDeviceParameters::ignore(3)
|
||||
assert_equal(dpc.to_string, "#1:A0/R0;#2:A1/R0.25;#3:ignore")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue