Using primary(layout) netlist as reference for primary parameters and compare delegate - this also removes some potential glitches

This commit is contained in:
Matthias Koefferlein
2021-07-29 01:15:35 +02:00
parent a90e14b692
commit 8b970039c0
13 changed files with 168 additions and 53 deletions
+10
View File
@@ -90,6 +90,16 @@ void Device::set_circuit (Circuit *circuit)
mp_circuit = circuit;
}
const Netlist *Device::netlist () const
{
return mp_circuit ? mp_circuit->netlist () : 0;
}
Netlist *Device::netlist ()
{
return mp_circuit ? mp_circuit->netlist () : 0;
}
void Device::set_name (const std::string &n)
{
m_name = n;
+10
View File
@@ -193,6 +193,16 @@ public:
return mp_circuit;
}
/**
* @brief Gets the netlist, the device lives in
*/
const Netlist *netlist () const;
/**
* @brief Gets the netlist, the device lives in
*/
Netlist *netlist ();
/**
* @brief Sets the name
*/
+29 -20
View File
@@ -22,11 +22,34 @@
#include "dbDeviceClass.h"
#include "dbDevice.h"
#include "dbNetlist.h"
#include "tlClassRegistry.h"
namespace db
{
// --------------------------------------------------------------------------------
/**
* @brief Returns the primary device class for both given devices
* One of the devices lives in a primary netlist. This one is taken for the device class.
*/
static const db::DeviceClass *primary_device_class (const db::Device &a, const db::Device &b)
{
tl_assert (a.device_class () != 0);
tl_assert (b.device_class () != 0);
const db::DeviceClass *dca = a.device_class ()->primary_class () ? a.device_class ()->primary_class () : a.device_class ();
const db::DeviceClass *dcb = b.device_class ()->primary_class () ? b.device_class ()->primary_class () : b.device_class ();
if (dca != dcb) {
// different devices, same category while sorting devices - take the one with the "lower" name
return dca->name () < dcb->name () ? dca : dcb;
} else {
return dca;
}
}
// --------------------------------------------------------------------------------
// EqualDeviceParameters implementation
@@ -36,7 +59,6 @@ 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)
@@ -112,21 +134,14 @@ bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) cons
seen.insert (c->first);
}
const std::vector<db::DeviceParameterDefinition> &pd = a.device_class ()->parameter_definitions ();
const std::vector<db::DeviceParameterDefinition> &pd = primary_device_class (a, b)->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 ()) {
if (p->is_primary () && seen.find (p->id ()) == seen.end ()) {
int cmp = compare_parameters (a.parameter_value (p->id ()), b.parameter_value (p->id ()));
if (cmp != 0) {
return cmp < 0;
}
}
}
return false;
@@ -166,13 +181,13 @@ bool AllDeviceParametersAreEqual::less (const db::Device &a, const db::Device &b
// DeviceClass class implementation
DeviceClass::DeviceClass ()
: m_strict (false), mp_netlist (0), m_supports_parallel_combination (false), m_supports_serial_combination (false)
: m_strict (false), mp_netlist (0), m_supports_parallel_combination (false), m_supports_serial_combination (false), mp_primary_class (0)
{
// .. nothing yet ..
}
DeviceClass::DeviceClass (const DeviceClass &other)
: gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), m_strict (false), mp_netlist (0), m_supports_parallel_combination (false), m_supports_serial_combination (false)
: gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), m_strict (false), mp_netlist (0), m_supports_parallel_combination (false), m_supports_serial_combination (false), mp_primary_class (0)
{
operator= (other);
}
@@ -299,10 +314,7 @@ 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 ();
}
const db::DeviceParameterCompareDelegate *pcd = primary_device_class (a, b)->parameter_compare_delegate ();
if (! pcd) {
pcd = &default_compare;
}
@@ -315,10 +327,7 @@ 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 ();
}
const db::DeviceParameterCompareDelegate *pcd = primary_device_class (a, b)->parameter_compare_delegate ();
if (! pcd) {
pcd = &default_compare;
}
+17
View File
@@ -734,6 +734,22 @@ public:
return mp_device_combiner.get ();
}
/**
* @brief Internally used by the netlist comparer to temporarily attach a device class pointing to the primary one
*/
void set_primary_class (const db::DeviceClass *primary) const
{
mp_primary_class = primary;
}
/**
* @brief Internally used by the netlist comparer to temporarily attach a device class pointing to the primary one
*/
const db::DeviceClass *primary_class () const
{
return mp_primary_class;
}
/**
* @brief Generate memory statistics
*/
@@ -762,6 +778,7 @@ private:
bool m_supports_parallel_combination;
bool m_supports_serial_combination;
std::map<size_t, size_t> m_equivalent_terminal_ids;
mutable const db::DeviceClass *mp_primary_class;
void set_netlist (db::Netlist *nl)
{
+1 -1
View File
@@ -44,7 +44,7 @@ Netlist::Netlist (NetlistManipulationCallbacks *callbacks)
}
Netlist::Netlist (const Netlist &other)
: gsi::ObjectBase (other), tl::Object (other), m_case_sensitive (true),
: gsi::ObjectBase (other), tl::Object (other),
m_valid_topology (false), m_lock_count (0),
m_circuit_by_name (this, &Netlist::begin_circuits, &Netlist::end_circuits),
m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits),
+31 -12
View File
@@ -3059,9 +3059,37 @@ NetlistComparer::unmatched_circuits (db::Netlist *a, db::Netlist *b, std::vector
}
}
static void clear_primary_classes (const db::Netlist *nl)
{
for (db::Netlist::const_device_class_iterator dc = nl->begin_device_classes (); dc != nl->end_device_classes (); ++dc) {
dc->set_primary_class (0);
}
}
bool
NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
{
bool res = false;
try {
res = compare_impl (a, b);
clear_primary_classes (a);
clear_primary_classes (b);
} catch (...) {
clear_primary_classes (a);
clear_primary_classes (b);
throw;
}
return res;
}
bool
NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
{
clear_primary_classes (a);
clear_primary_classes (b);
m_case_sensitive = combined_case_sensitive (a, b);
// we need to create a copy because this method is supposed to be const.
@@ -3130,21 +3158,12 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
}
}
// impose the compare tolerances of the layout (first netlist) on the schematic (second netlist)
// TODO: this is kind of clumsy. But it's very important to use the same device sorting for both netlists, so we play this trick.
// A better solution was to have a common compare framework for both netlists.
// Register the primary netlist's device classes as primary ones for the second netlist's device classes.
// This way, the tolerances and parameter definitions are imposed on the second netlist, creating a common basis.
for (std::map<size_t, std::pair<const db::DeviceClass *, const db::DeviceClass *> >::const_iterator i = cat2dc.begin (); i != cat2dc.end (); ++i) {
if (i->second.first && i->second.second) {
const db::DeviceClass *da = i->second.first;
db::DeviceClass *db = const_cast<db::DeviceClass *> (i->second.second);
const db::DeviceParameterCompareDelegate *cmp = da->parameter_compare_delegate ();
db->set_parameter_compare_delegate (const_cast<db::DeviceParameterCompareDelegate *> (cmp));
i->second.second->set_primary_class (i->second.first);
}
}
// decide whether to use a device category in strict mode
+1
View File
@@ -354,6 +354,7 @@ private:
NetlistComparer &operator= (const NetlistComparer &);
protected:
bool compare_impl (const db::Netlist *a, const db::Netlist *b) const;
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<std::pair<const Net *, const Net *>, bool> > &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;
std::string generate_subcircuits_not_verified_warning (const db::Circuit *ca, const std::set<const db::Circuit *> &verified_circuits_a, const db::Circuit *cb, const std::set<const db::Circuit *> &verified_circuits_b) const;
-3
View File
@@ -625,9 +625,6 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin
std::map<std::string, double>::const_iterator v = params.find (i->name ());
if (v != params.end ()) {
device->set_parameter_value (i->id (), v->second / i->si_scaling ());
// Make given parameters primary. This way they are netlisted again and participate in netlist compare when
// they are made primary in the extracted netlist too.
i->set_is_primary (true);
} else if (i->id () == defp) {
device->set_parameter_value (i->id (), value / i->si_scaling ());
}
+10 -1
View File
@@ -404,6 +404,13 @@ TEST(0_EqualDeviceParameters)
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), false);
EXPECT_EQ (dc.equal (d2, d1), false);
EXPECT_EQ (dc.less (d1, d2), false);
EXPECT_EQ (dc.less (d2, d1), true);
*eqp += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_W, true); // ignore W
EXPECT_EQ (dc.equal (d1, d2), true);
EXPECT_EQ (dc.equal (d2, d1), true);
EXPECT_EQ (dc.less (d1, d2), false);
@@ -959,7 +966,9 @@ TEST(5_BufferTwoPathsDifferentParameters)
EXPECT_EQ (good, false);
logger.clear ();
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (new db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.5, 0.0));
db::EqualDeviceParameters *eql = new db::EqualDeviceParameters ();
*eql += db::EqualDeviceParameters (db::DeviceClassMOS3Transistor::param_id_L, 1.5, 0.0);
nl1.device_class_by_name ("NMOS")->set_parameter_compare_delegate (eql);
good = comp.compare (&nl1, &nl2);
EXPECT_EQ (logger.text (),