Some tests added.

This commit is contained in:
Matthias Koefferlein 2021-07-27 23:08:34 +02:00
parent 42b7290fe5
commit a90e14b692
4 changed files with 285 additions and 2 deletions

View File

@ -310,7 +310,7 @@ class DB_PUBLIC EqualDeviceParameters
public:
EqualDeviceParameters ();
EqualDeviceParameters (size_t parameter_id, bool ignore = false);
EqualDeviceParameters (size_t parameter_id, double relative, double absolute);
EqualDeviceParameters (size_t parameter_id, double absolute, double relative);
virtual bool less (const db::Device &a, const db::Device &b) const;

View File

@ -4712,3 +4712,189 @@ TEST(29_EmptySubCircuitsFromSPICE)
EXPECT_EQ (comp.compare (&a, &b), true);
EXPECT_EQ (comp.compare (&a, &c), false);
}
TEST(30_ComparePrimaryAndOtherParameters)
{
db::Netlist nl1, nl2;
db::DeviceClass *dc1, *dc2;
db::Circuit *circuit;
db::Device *d;
db::Net *n;
std::string txt;
bool good;
dc1 = new db::DeviceClassResistor ();
dc1->set_name ("RES");
nl1.add_device_class (dc1);
circuit = new db::Circuit ();
circuit->set_name ("X");
d = new db::Device ();
d->set_device_class (dc1);
d->set_name ("D");
d->set_parameter_value (db::DeviceClassResistor::param_id_L, 1.0);
d->set_parameter_value (db::DeviceClassResistor::param_id_R, 10.0);
d->set_parameter_value (db::DeviceClassResistor::param_id_W, 0.25);
circuit->add_device (d);
n = new db::Net ();
circuit->add_net (n);
n->set_name ("1");
d->connect_terminal (db::DeviceClassResistor::terminal_id_A, n);
n->add_pin (db::NetPinRef (circuit->add_pin ("1").id ()));
n = new db::Net ();
circuit->add_net (n);
n->set_name ("2");
d->connect_terminal (db::DeviceClassResistor::terminal_id_B, n);
n->add_pin (db::NetPinRef (circuit->add_pin ("2").id ()));
nl1.add_circuit (circuit);
dc2 = new db::DeviceClassResistor ();
dc2->set_name ("RES");
nl2.add_device_class (dc2);
circuit = new db::Circuit ();
circuit->set_name ("X");
d = new db::Device ();
d->set_device_class (dc2);
d->set_name ("D");
d->set_parameter_value (db::DeviceClassResistor::param_id_L, 1.1); // differs
d->set_parameter_value (db::DeviceClassResistor::param_id_R, 10.0);
d->set_parameter_value (db::DeviceClassResistor::param_id_W, 0.20); // differs
circuit->add_device (d);
n = new db::Net ();
circuit->add_net (n);
n->set_name ("1");
d->connect_terminal (db::DeviceClassResistor::terminal_id_A, n);
n->add_pin (db::NetPinRef (circuit->add_pin ("1").id ()));
n = new db::Net ();
circuit->add_net (n);
n->set_name ("2");
d->connect_terminal (db::DeviceClassResistor::terminal_id_B, n);
n->add_pin (db::NetPinRef (circuit->add_pin ("2").id ()));
nl2.add_circuit (circuit);
NetlistCompareTestLogger logger;
db::NetlistComparer comp (&logger);
comp.set_dont_consider_net_names (true);
good = comp.compare (&nl1, &nl2);
txt = logger.text ();
// we did not enable L and W, hence that works
EXPECT_EQ (good, true);
EXPECT_EQ (txt,
"begin_circuit X X\n"
"match_ambiguous_nets 1 1\n"
"match_ambiguous_nets 2 2\n"
"match_pins 1 1\n"
"match_pins 2 2\n"
"match_devices D D\n"
"end_circuit X X MATCH"
);
// changing R will make the compare fail
d->set_parameter_value (db::DeviceClassResistor::param_id_R, 12.0);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, false);
// if we install a delegate which introduces a tolerance (absolute 1) it will still not match
dc1->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassResistor::param_id_R, 1.0, 0.0));
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, false);
// if we install a delegate which introduces a tolerance (absolute 2.0) it will match
dc1->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassResistor::param_id_R, 2.0, 0.0));
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, true);
// removing the comparer will make it non-matching
dc1->set_parameter_compare_delegate (0);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, false);
// disabling the parameter will make it match too
dc1->parameter_definition_non_const (db::DeviceClassResistor::param_id_R)->set_is_primary (false);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, true);
// enabling the parameter again will make it mismatch again
dc1->parameter_definition_non_const (db::DeviceClassResistor::param_id_R)->set_is_primary (true);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, false);
// disabling the parameter in the second netlist will make it match too
dc2->parameter_definition_non_const (db::DeviceClassResistor::param_id_R)->set_is_primary (false);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, true);
// enabling the parameter again will make it mismatch again
dc2->parameter_definition_non_const (db::DeviceClassResistor::param_id_R)->set_is_primary (true);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, false);
// we can install an ignore handler to make it match again
dc1->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassResistor::param_id_R, true));
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, true);
// if we enable the L parameter we'll get a mismatch again (but we have to enable it in both netlists)
dc1->parameter_definition_non_const (db::DeviceClassResistor::param_id_L)->set_is_primary (true);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, true);
dc2->parameter_definition_non_const (db::DeviceClassResistor::param_id_L)->set_is_primary (true);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, false);
// until we install another tolerance
*dynamic_cast<db::EqualDeviceParameters *> (dc1->parameter_compare_delegate ()) += db::EqualDeviceParameters (db::DeviceClassResistor::param_id_L, 0.11, 0.0);
logger.clear ();
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (good, true);
}

View File

@ -183,7 +183,27 @@ module LVS
# @synopsis tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance])
# See \Netter#tolerance for a description of that function.
%w(schematic compare join_symmetric_nets tolerance blank_circuit align same_nets same_nets! same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
# %LVS%
# @name ignore_parameter
# @brief Specifies whether to ignore a parameter from a given device class for the compare
# @synopsis ignore_parameter(device_class_name, parameter_name)
# See \Netter#ignore_parameter for a description of that function.
# %LVS%
# @name enable_parameter
# @brief Specifies whether to enable a parameter from a given device class for the netlisting and default compare
# @synopsis enable_parameter(device_class_name, parameter_name)
# See \Netter#enable_parameter for a description of that function.
# %LVS%
# @name disable_parameter
# @brief Specifies whether to disable a parameter from a given device class for the netlisting and default compare
# @synopsis disable_parameter(device_class_name, parameter_name)
# See \Netter#disable_parameter for a description of that function.
%w(schematic compare join_symmetric_nets tolerance ignore_parameter enable_parameter disable_parameter
blank_circuit align same_nets same_nets! same_circuits same_device_classes equivalent_pins
min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
eval <<"CODE"
def #{f}(*args)
_netter.#{f}(*args)

View File

@ -164,6 +164,83 @@ module LVS
end
# %LVS%
# @name ignore_parameter
# @brief Indicates whether not to compare a specific parameter for a given device class name
# @synopsis ignore_parameter(device_class_name, parameter_name)
def ignore_parameter(device_class_name, parameter_name)
device_class_name.is_a?(String) || raise("Device class argument of 'ignore_parameter' must be a string")
parameter_name.is_a?(String) || raise("Parameter name argument of 'ignore_parameter' must be a string")
if self._l2n_data
# already extracted
self._ignore_parameter(self._l2n_data, device_class_name, parameter_name)
else
@post_extract_config << lambda { |l2n| self._ignore_parameter(l2n, device_class_name, parameter_name) }
end
end
def _ignore_parameter(l2n, device_class_name, parameter_name)
dc = l2n.netlist.device_class_by_name(device_class_name)
if dc && dc.has_parameter?(parameter_name)
ep = RBA::EqualDeviceParameters::ignore(dc.parameter_id(parameter_name))
if dc.equal_parameters == nil
dc.equal_parameters = ep
else
dc.equal_parameters += ep
end
end
end
# %LVS%
# @name enable_parameter
# @brief Indicates whether to enable a specific parameter for a given device
# @synopsis enable_parameter(device_class_name, parameter_name)
# Enabling a parameter has two effects: first the parameter is netlisted and second
# the parameter is compared in the netlist compare - provided it is given in the schematic.
# Setting a tolerance or using a custom device comparer will override the last rule.
# %LVS%
# @name disable_parameter
# @brief Indicates whether to disable a specific parameter for a given device
# @synopsis disable_parameter(device_class_name, parameter_name)
# Disabling a parameter has two effects: first the parameter is not netlisted and second
# the parameter is compared in the netlist compare - provided it is given in the schematic.
# Setting a tolerance or using a custom device comparer will override the last rule.
# To disable a parameter for compare only, \ignore_parameter can be used.
[ :enable_parameter, :disable_parameter ].each do |mn|
eval <<"CODE"
def #{mn}(device_class_name, parameter_name)
device_class_name.is_a?(String) || raise("Device class argument of '#{mn}' must be a string")
parameter_name.is_a?(String) || raise("Parameter name argument of '#{mn}' must be a string")
if self._l2n_data
# already extracted
self._enable_parameter(self._l2n_data, device_class_name, parameter_name, :#{mn} == :enable_parameter)
else
@post_extract_config << lambda { |l2n| self._enable_parameter(l2n, device_class_name, parameter_name, :#{mn} == :enable_parameter) }
end
end
CODE
end
def _enable_parameter(l2n, device_class_name, parameter_name, enable)
dc = l2n.netlist.device_class_by_name(device_class_name)
if dc && dc.has_parameter?(parameter_name)
dc.enable_parameter(parameter_name, enable)
end
end
# %LVS%
# @name align
# @brief Aligns the extracted netlist vs. the schematic