Merge pull request #882 from KLayout/issue-880

Issue 880
This commit is contained in:
Matthias Köfferlein 2021-07-31 11:01:42 +02:00 committed by GitHub
commit 32254ffdca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 2137 additions and 97 deletions

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;

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
*/

View File

@ -22,16 +22,50 @@
#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
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 +91,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 +127,23 @@ 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 = primary_device_class (a, b)->parameter_definitions ();
for (std::vector<db::DeviceParameterDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
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;
}
@ -109,58 +177,17 @@ 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
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);
}
@ -279,22 +306,15 @@ 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)
{
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;
}
@ -307,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;
}

View File

@ -309,11 +309,14 @@ class DB_PUBLIC EqualDeviceParameters
{
public:
EqualDeviceParameters ();
EqualDeviceParameters (size_t parameter_id);
EqualDeviceParameters (size_t parameter_id, double relative, double absolute);
EqualDeviceParameters (size_t parameter_id, bool ignore = false);
EqualDeviceParameters (size_t parameter_id, double absolute, double relative);
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> &parameter_definitions_non_const ()
{
return m_parameter_definitions;
}
/**
* @brief Adds a parameter definition
*/
@ -723,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
*/
@ -751,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)
{

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),

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

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;

View File

@ -620,8 +620,8 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin
defp = db::DeviceClassInductor::param_id_L;
}
const std::vector<db::DeviceParameterDefinition> &pd = cls->parameter_definitions ();
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = pd.begin (); i != pd.end (); ++i) {
std::vector<db::DeviceParameterDefinition> &pd = cls->parameter_definitions_non_const ();
for (std::vector<db::DeviceParameterDefinition>::iterator i = pd.begin (); i != pd.end (); ++i) {
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 ());

View File

@ -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"

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 (),
@ -4712,3 +4721,164 @@ 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);
// 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
dc1->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

@ -55,6 +55,24 @@ See <a href="/about/lvs_ref_netter.xml#compare">Netter#compare</a> for a descrip
<p>
See <a href="/about/lvs_ref_netter.xml#consider_net_names">Netter#consider_net_names</a> for a description of that function.
</p>
<a name="disable_parameter"/><h2>"disable_parameter" - Specifies whether to disable a parameter from a given device class for netlisting and default compare</h2>
<keyword name="disable_parameter"/>
<p>Usage:</p>
<ul>
<li><tt>disable_parameter(device_class_name, parameter_name)</tt></li>
</ul>
<p>
See <a href="/about/lvs_ref_netter.xml#disable_parameter">Netter#disable_parameter</a> for a description of that function.
</p>
<a name="enable_parameter"/><h2>"enable_parameter" - Specifies whether to enable a parameter from a given device class for netlisting and default compare</h2>
<keyword name="enable_parameter"/>
<p>Usage:</p>
<ul>
<li><tt>enable_parameter(device_class_name, parameter_name)</tt></li>
</ul>
<p>
See <a href="/about/lvs_ref_netter.xml#enable_parameter">Netter#enable_parameter</a> for a description of that function.
</p>
<a name="equivalent_pins"/><h2>"equivalent_pins" - Marks pins as equivalent</h2>
<keyword name="equivalent_pins"/>
<p>Usage:</p>
@ -64,6 +82,15 @@ See <a href="/about/lvs_ref_netter.xml#consider_net_names">Netter#consider_net_n
<p>
See <a href="/about/lvs_ref_netter.xml#equivalent_pins">Netter#equivalent_pins</a> for a description of that function.
</p>
<a name="ignore_parameter"/><h2>"ignore_parameter" - Specifies whether to ignore a parameter from a given device class for the compare</h2>
<keyword name="ignore_parameter"/>
<p>Usage:</p>
<ul>
<li><tt>ignore_parameter(device_class_name, parameter_name)</tt></li>
</ul>
<p>
See <a href="/about/lvs_ref_netter.xml#ignore_parameter">Netter#ignore_parameter</a> for a description of that function.
</p>
<a name="join_symmetric_nets"/><h2>"join_symmetric_nets" - Joins symmetric nets of selected circuits on the extracted netlist</h2>
<keyword name="join_symmetric_nets"/>
<p>Usage:</p>

View File

@ -127,6 +127,38 @@ will employ net names to resolve ambiguities. If set to false,
ambiguities will be resolved based on the topology alone. Topology
resolution is more expensive.
</p>
<a name="disable_parameter"/><h2>"disable_parameter" - Indicates whether to disable a specific parameter for a given device</h2>
<keyword name="disable_parameter"/>
<p>Usage:</p>
<ul>
<li><tt>disable_parameter(device_class_name, parameter_name)</tt></li>
</ul>
<p>
Disabling a parameter is the inverse of <a href="#enable_parameter">enable_parameter</a>. Disabling a parameter will
reset the "primary" flag of the parameter. This has several effects - e.g. the parameter will not be
used in device compare during netlist matching by default.
</p><p>
This is not a strong concept but rather
a hint for the system. Disabling a parameter for netlist compare without side effects
is possible with the <a href="#ignore_parameter">ignore_parameter</a> function. In the same way, <a href="#tolerance">tolerance</a> will enable a parameter for
netlist compare regardless of the "primary" status of the parameter.
</p>
<a name="enable_parameter"/><h2>"enable_parameter" - Indicates whether to enable a specific parameter for a given device</h2>
<keyword name="enable_parameter"/>
<p>Usage:</p>
<ul>
<li><tt>enable_parameter(device_class_name, parameter_name)</tt></li>
</ul>
<p>
The parameter is made "primary" which enables further applications - e.g. it is netlisted
for some elements which normally would not print that parameter, and the parameter
is compared in the default device compare scheme during netlist matching.
</p><p>
Enabling a parameter is rather a hint for the system and the effects can be controlled
by other means, so this is not a strong concept. For example, once a <a href="#tolerance">tolerance</a> is
specified for a parameter, the "primary" flag of the parameter is not considered anymore.
The inverse the this function is <a href="#disable_parameter">disable_parameter</a>.
</p>
<a name="equivalent_pins"/><h2>"equivalent_pins" - Marks pins as equivalent</h2>
<keyword name="equivalent_pins"/>
<p>Usage:</p>
@ -154,6 +186,20 @@ case pin names for SPICE netlists.
</p><p>
Use this method andwhere in the script before the <a href="#compare">compare</a> call.
</p>
<a name="ignore_parameter"/><h2>"ignore_parameter" - Skip a specific parameter for a given device class name during device compare</h2>
<keyword name="ignore_parameter"/>
<p>Usage:</p>
<ul>
<li><tt>ignore_parameter(device_class_name, parameter_name)</tt></li>
</ul>
<p>
Use this function is ignore a parameter for a particular device class during the netlist compare.
Some parameters - for example "L" and "W" parameters of the resistor device - are "secondary" parameters
which are not ignored by default. Using "ignore_parameter" on such devices does not have an effect.
</p><p>
"ignore_parameter" and "tolerance" only have an effect with the default device comparer. Using a custom device comparer
will override the definitions by "ignore_parameter" or "tolerance".
</p>
<a name="join_symmetric_nets"/><h2>"join_symmetric_nets" - Joins symmetric nets of selected circuits on the extracted netlist</h2>
<keyword name="join_symmetric_nets"/>
<p>Usage:</p>
@ -395,5 +441,14 @@ Tolerances can be given in absolute units or relative or both.
The relative tolerance is given as a factor, so 0.1 is a 10% tolerance.
Absolute and relative tolerances add, so specifying both allows for a larger
deviation.
</p><p>
Some device parameters - like the resistor's "L" and "W" parameters - are not compared by default.
These are "secondary" device parameters. Using a tolerance on such parameters will make these parameters
being compared even if they are secondary ones.
</p><p>
A function is skip a parameter during the device compare is "ignore_parameter".
</p><p>
"tolerance" and "ignore_parameter" only have an effect with the default device comparer. Using a custom device comparer
will override the definitions by "ignore_parameter" or "tolerance".
</p>
</doc>

View File

@ -205,6 +205,53 @@ same_device_classes("POLYRES", nil)</pre>
<pre>tolerance("NMOS", "L", 0.05, 0.01)
tolerance("NMOS", "L", :absolute => 0.05, :relative => 0.01)</pre>
<h2>Ignoring parameters</h2>
<p>
It is possible to ignore certain parameters from certain devices in the netlist compare.
For example, if you don't want to compare the "L" parameter of the "NMOS" devices, use this statement:
</p>
<pre>ignore_parameter("NMOS", "L")</pre>
<p>
This statement can be put into the script anywhere before the "compare" statement.
</p>
<p>
By default, only "primary" parameters are compared. For a resistor for example, "R" is a primary parameter, the other ones
like "L", "W", "A" and "P" are not. Using "tolerance" will implicitly enable a parameter - even if it is not a primary one - while "ignore_parameter" will disable
a parameter for compare - even if it is a primary one.
</p>
<h2>Enabling and disabling parameters</h2>
<p>
As mentioned before, some device parameters are primary while other are not. For example, for the resistor device,
"R" (the resistance value) is a primary parameter while the device length ("L") is not. You can make the "L" parameter
primary for a device class called "RES" by using:
</p>
<pre>enable_parameter("RES", "L")</pre>
<p>
This has two effects: first, the "L" parameter is written into the Spice output netlist and in addition it is compared against
the schematic "L" parameter.
</p>
<p>
Correspondingly, a primary parameter can be disabled using:
</p>
<pre>disable_parameter("RES", "R")</pre>
<p>
This behavior is overridden by a "tolerance" or "ignore_parameter" specification for that parameter or if a custom
device comparer is installed. Netlisting is affected only for the elementary devices (R, C and L) and any Spice writer
delegate can choose to ignore the primary flag. A custom device comparer may also ignore this flag.
So after all, enabling or disabling a parameter is not a strong concept but rather a hint.
</p>
<h2>Pin swapping</h2>
<p>

View File

@ -362,18 +362,11 @@ extract_devices(bjt3(model_name), { "C" => collector, "B" => base, "E" => emitte
</p>
<p>
Parameters can be fully enabled by using "enable_parameter" on the device class.
Hence it is possible to enable "W" and "L" on a resistor type using the following code:
</p>
<pre>dc = extract_devices(resistor("RES", 1), ...)
dc.enable_parameter("W", true)
dc.enable_parameter("L", true)
</pre>
<p>
This will modify the parameters of the generated device class such that "W" and "L" are
fully enabled parameters.
Parameters can be fully enabled by using <a href="/about/lvs_ref_global.xml#enable_parameter">enable_parameter</a>
or disabled using <a href="/about/lvs_ref_global.xml#disable_parameter">disable_parameter</a>.
<a href="/about/lvs_ref_global.xml#tolerance">tolerance</a> can be used to enable a parameter for compare
and to specify a compare tolerance.
<a href="/about/lvs_ref_global.xml#ignore_parameter">ignore_parameter</a> can be used to ignore a parameter in the compare step.
</p>
<p>
@ -397,8 +390,7 @@ extract_devices(resistor("RES", 1, MyResistor), ...)
</pre>
<p>
The effect of this code is the same than the first one, but using a custom
device class opens the option to supply additional parameters for example
Using a custom device class opens the option to supply additional parameters for example
or to implement some entirely new device while using the extraction
mechanics of the resistor extractor. The only requirement is compatibility of
the parameter and terminal definitions.

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<doc>

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 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 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

@ -110,6 +110,15 @@ module LVS
# The relative tolerance is given as a factor, so 0.1 is a 10% tolerance.
# Absolute and relative tolerances add, so specifying both allows for a larger
# deviation.
#
# Some device parameters - like the resistor's "L" and "W" parameters - are not compared by default.
# These are "secondary" device parameters. Using a tolerance on such parameters will make these parameters
# being compared even if they are secondary ones.
#
# A function is skip a parameter during the device compare is "ignore_parameter".
#
# "tolerance" and "ignore_parameter" only have an effect with the default device comparer. Using a custom device comparer
# will override the definitions by "ignore_parameter" or "tolerance".
def tolerance(device_class_name, parameter_name, *args)
@ -164,6 +173,99 @@ module LVS
end
# %LVS%
# @name ignore_parameter
# @brief Skip a specific parameter for a given device class name during device compare
# @synopsis ignore_parameter(device_class_name, parameter_name)
#
# Use this function is ignore a parameter for a particular device class during the netlist compare.
# Some parameters - for example "L" and "W" parameters of the resistor device - are "secondary" parameters
# which are not ignored by default. Using "ignore_parameter" on such devices does not have an effect.
#
# "ignore_parameter" and "tolerance" only have an effect with the default device comparer. Using a custom device comparer
# will override the definitions by "ignore_parameter" or "tolerance".
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)
# The parameter is made "primary" which enables further applications - e.g. it is netlisted
# for some elements which normally would not print that parameter, and the parameter
# is compared in the default device compare scheme during netlist matching.
#
# Enabling a parameter is rather a hint for the system and the effects can be controlled
# by other means, so this is not a strong concept. For example, once a \tolerance is
# specified for a parameter, the "primary" flag of the parameter is not considered anymore.
# The inverse the this function is \disable_parameter.
# %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 is the inverse of \enable_parameter. Disabling a parameter will
# reset the "primary" flag of the parameter. This has several effects - e.g. the parameter will not be
# used in device compare during netlist matching by default.
#
# This is not a strong concept but rather
# a hint for the system. Disabling a parameter for netlist compare without side effects
# is possible with the \ignore_parameter function. In the same way, \tolerance will enable a parameter for
# netlist compare regardless of the "primary" status of the parameter.
[ :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

View File

@ -261,3 +261,10 @@ TEST(28_BlackBoxDevicesWithBlank)
run_test (_this, "bbdevices5b", "bbdevices5.gds");
run_test (_this, "bbdevices6b", "bbdevices6.gds");
}
TEST(29_DeviceCombineAndTolerances)
{
run_test (_this, "res_combine1", "res_combine.gds");
run_test (_this, "res_combine2", "res_combine.gds");
run_test (_this, "res_combine3", "res_combine.gds");
}

View File

@ -145,7 +145,7 @@ TEST(15_private)
TEST(16_private)
{
// test_is_long_runner ();
// test_is_long_runner ();lvs-blackbox
run_test (_this, "test_16.lvs", "test_16.cir.gz", "test_16.gds.gz", true);
}

BIN
testdata/lvs/res_combine.gds vendored Normal file

Binary file not shown.

7
testdata/lvs/res_combine1.cir vendored Normal file
View File

@ -0,0 +1,7 @@
* Extracted by KLayout
* cell Res2
.SUBCKT Res2
* device instance $1 r0 *1 110.14,51.795 RPP1
R$1 1 2 95 RPP1 L=420U W=2.21052631579U
.ENDS Res2

96
testdata/lvs/res_combine1.lvs vendored Normal file
View File

@ -0,0 +1,96 @@
source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("res_combine_schematic.cir")
deep
# -------------------------------------------------------------------
# Layers
pimp = input(7, 0)
poly_dg = input(13, 0)
cont = input(15, 0)
met1_dg = input(16, 0)
sblk = input(34, 0)
rp_1 = sblk & poly_dg
rpp1 = rp_1 & pimp
p1trm = poly_dg - rpp1
class ResistorExtractor < RBA::GenericDeviceExtractor
def initialize(name, sheet_rho)
self.name = name
@sheet_rho = sheet_rho
end
def setup
define_layer("C", "Conductor")
define_layer("R", "Resistor")
register_device_class(RBA::DeviceClassResistor::new)
end
def get_connectivity(layout, layers)
# this "connectivity" forms the shape clusters that make up the device
conn = RBA::Connectivity::new
conn.connect(layers[0], layers[1]) # collect touching contacts
conn.connect(layers[1], layers[1]) # combine resistor shapes into one area
conn
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are defined with "define_layer"
conductor = layer_geometry[0]
resistor = layer_geometry[1]
resistor_regions = resistor.merged
resistor_regions.each do |r|
terminals = conductor.interacting(resistor)
if terminals.size != 2
error("Resistor shape does not touch marker border in exactly two places", r)
else
double_width = 0
(terminals.edges & resistor.edges).merged.each do |e|
double_width += e.length
end
# A = L*W
# -> L = A/W
a = r.area*dbu*dbu
w = (double_width / 2.0)*dbu
l = a / w
device = create_device
device.set_parameter(RBA::DeviceClassResistor::PARAM_R, @sheet_rho * l / w);
device.set_parameter(RBA::DeviceClassResistor::PARAM_A, a)
device.set_parameter(RBA::DeviceClassResistor::PARAM_L, l)
device.set_parameter(RBA::DeviceClassResistor::PARAM_P, 2*l+2*w)
device.set_parameter(RBA::DeviceClassResistor::PARAM_W, w)
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_A, 0, terminals[0]);
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_B, 0, terminals[1]);
end
end
end
end
# enable/disable
enable_parameter("RPP1", "L")
enable_parameter("RPP1", "W")
disable_parameter("RPP1", "R")
extract_devices(ResistorExtractor::new("RPP1", 0.5), # intentionally wrong: 1565.15/5
{ "C" => p1trm, "R" => rpp1 })
connect(met1_dg, cont)
connect(p1trm, cont)
netlist.flatten_circuit("Res1")
schematic.flatten_circuit("RES1")
schematic.simplify
# Netlist vs. netlist
align
netlist.simplify
compare

197
testdata/lvs/res_combine1.lvsdb.1 vendored Normal file
View File

@ -0,0 +1,197 @@
#%lvsdb-klayout
# Layout
layout(
top(Res2)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l4 '15/0')
layer(l3 '16/0')
layer(l1)
# Mask layer connectivity
connect(l4 l4 l3 l1)
connect(l3 l4 l3)
connect(l1 l4 l1)
# Device class section
class(RPP1 RES
param(R 0 0)
param(L 1 0)
param(W 1 0)
)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$RPP1 RPP1
terminal(A
rect(l1 (0 0) (540 2000))
)
terminal(B
rect(l1 (10540 0) (540 2000))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(Res2
# Circuit boundary
rect((8285 720) (117975 57350))
# Nets with their geometries
net(1
rect(l4 (120580 32490) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-22355 1390) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-21520 1755) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (0 -4795) (1065 5850))
rect(l3 (-5155 -6930) (52985 1475))
rect(l3 (-27585 -395) (1065 5850))
rect(l3 (20990 -5850) (1065 5850))
rect(l3 (-1275 -1760) (340 1920))
rect(l3 (-22475 -1890) (340 1920))
rect(l3 (-21640 -1525) (340 1920))
rect(l1 (42935 -2385) (540 2000))
rect(l1 (-22675 -1970) (540 2000))
rect(l1 (-21840 -1605) (540 2000))
)
net(2
rect(l4 (19795 5575) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (-195 -995) (2395 2500))
rect(l3 (-2480 -1785) (340 1920))
rect(l1 (-500 -1960) (540 2000))
)
# Devices and their connections
device(1 D$RPP1
device(D$RPP1 location(30 -3970))
device(D$RPP1 location(-65 -8175))
device(D$RPP1 location(-205 -12595))
device(D$RPP1 location(-225 -16825))
device(D$RPP1 location(-320 -20985))
device(D$RPP1 location(-22135 30))
device(D$RPP1 location(-22105 -3940))
device(D$RPP1 location(-22200 -8145))
device(D$RPP1 location(-22340 -12565))
device(D$RPP1 location(-22360 -16795))
device(D$RPP1 location(-22455 -20955))
device(D$RPP1 location(-43435 425))
device(D$RPP1 location(-43405 -3545))
device(D$RPP1 location(-43500 -7750))
device(D$RPP1 location(-43640 -12170))
device(D$RPP1 location(-43660 -16400))
device(D$RPP1 location(-43755 -20560))
device(D$RPP1 location(-100755 -30885))
device(D$RPP1 location(-100850 -35090))
device(D$RPP1 location(-100990 -39510))
device(D$RPP1 location(-101010 -43740))
device(D$RPP1 location(-101105 -47900))
device(D$RPP1 location(-81920 -3545))
device(D$RPP1 location(-82015 -7750))
device(D$RPP1 location(-82155 -12170))
device(D$RPP1 location(-82175 -16400))
device(D$RPP1 location(-63835 -30780))
device(D$RPP1 location(-63930 -34985))
device(D$RPP1 location(-64070 -39405))
device(D$RPP1 location(-64090 -43635))
device(D$RPP1 location(-82380 -26810))
device(D$RPP1 location(-82270 -20560))
device(D$RPP1 location(-82350 -30780))
device(D$RPP1 location(-82445 -34985))
device(D$RPP1 location(-82585 -39405))
device(D$RPP1 location(-82605 -43635))
device(D$RPP1 location(-82700 -47795))
device(D$RPP1 location(-64185 -47795))
device(D$RPP1 location(-63435 640))
device(D$RPP1 location(-63405 -3330))
device(D$RPP1 location(-63500 -7535))
device(D$RPP1 location(-63640 -11955))
device(D$RPP1 location(-63660 -16185))
device(D$RPP1 location(-63755 -20345))
device(D$RPP1 location(-63865 -26810))
device(D$RPP1 location(-100465 855))
device(D$RPP1 location(-81950 425))
device(D$RPP1 location(-100435 -3115))
device(D$RPP1 location(-100530 -7320))
device(D$RPP1 location(-100670 -11740))
device(D$RPP1 location(-100690 -15970))
device(D$RPP1 location(-100785 -20130))
device(D$RPP1 location(-100785 -26915))
connect(5 A B)
connect(11 A B)
connect(17 A B)
connect(22 B B)
location(110140 51795)
param(R 95)
param(L 420)
param(W 2.21052631579)
param(A 1080)
param(P 1296)
terminal(A 1)
terminal(B 2)
)
)
)
# Reference netlist
reference(
# Device class section
class(RPP1 RES)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(RES2
# Nets
net(1 name(GND))
net(2 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(GND))
pin(2 name(VDD))
# Devices and their connections
device(1 RPP1
name(I0.I106.R0)
param(R 59475.7)
param(L 420)
param(W 2.21052631579)
param(A 0)
param(P 0)
terminal(A 2)
terminal(B 1)
)
)
)
# Cross reference
xref(
circuit(Res2 RES2 match
xref(
net(1 1 warning)
net(2 2 warning)
pin(() 0 match)
pin(() 1 match)
device(1 1 match)
)
)
)

197
testdata/lvs/res_combine1.lvsdb.2 vendored Normal file
View File

@ -0,0 +1,197 @@
#%lvsdb-klayout
# Layout
layout(
top(Res2)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l4 '15/0')
layer(l3 '16/0')
layer(l1)
# Mask layer connectivity
connect(l4 l4 l3 l1)
connect(l3 l4 l3)
connect(l1 l4 l1)
# Device class section
class(RPP1 RES
param(R 0 0)
param(L 1 0)
param(W 1 0)
)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$RPP1 RPP1
terminal(A
rect(l1 (0 0) (540 2000))
)
terminal(B
rect(l1 (10540 0) (540 2000))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(Res2
# Circuit boundary
rect((8285 720) (117975 57350))
# Nets with their geometries
net(1
rect(l4 (120580 32490) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-22355 1390) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-21520 1755) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (0 -4795) (1065 5850))
rect(l3 (-5155 -6930) (52985 1475))
rect(l3 (-27585 -395) (1065 5850))
rect(l3 (20990 -5850) (1065 5850))
rect(l3 (-1275 -1760) (340 1920))
rect(l3 (-22475 -1890) (340 1920))
rect(l3 (-21640 -1525) (340 1920))
rect(l1 (42935 -2385) (540 2000))
rect(l1 (-22675 -1970) (540 2000))
rect(l1 (-21840 -1605) (540 2000))
)
net(2
rect(l4 (19795 5575) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (-195 -995) (2395 2500))
rect(l3 (-2480 -1785) (340 1920))
rect(l1 (-500 -1960) (540 2000))
)
# Devices and their connections
device(1 D$RPP1
device(D$RPP1 location(30 -3970))
device(D$RPP1 location(-205 -12595))
device(D$RPP1 location(-225 -16825))
device(D$RPP1 location(-320 -20985))
device(D$RPP1 location(-65 -8175))
device(D$RPP1 location(-22135 30))
device(D$RPP1 location(-22105 -3940))
device(D$RPP1 location(-22340 -12565))
device(D$RPP1 location(-22360 -16795))
device(D$RPP1 location(-22455 -20955))
device(D$RPP1 location(-22200 -8145))
device(D$RPP1 location(-43435 425))
device(D$RPP1 location(-43405 -3545))
device(D$RPP1 location(-43640 -12170))
device(D$RPP1 location(-43660 -16400))
device(D$RPP1 location(-43755 -20560))
device(D$RPP1 location(-43500 -7750))
device(D$RPP1 location(-100755 -30885))
device(D$RPP1 location(-100990 -39510))
device(D$RPP1 location(-101010 -43740))
device(D$RPP1 location(-101105 -47900))
device(D$RPP1 location(-100850 -35090))
device(D$RPP1 location(-81920 -3545))
device(D$RPP1 location(-82155 -12170))
device(D$RPP1 location(-82175 -16400))
device(D$RPP1 location(-63835 -30780))
device(D$RPP1 location(-64070 -39405))
device(D$RPP1 location(-64090 -43635))
device(D$RPP1 location(-82380 -26810))
device(D$RPP1 location(-82270 -20560))
device(D$RPP1 location(-82350 -30780))
device(D$RPP1 location(-82585 -39405))
device(D$RPP1 location(-82605 -43635))
device(D$RPP1 location(-82700 -47795))
device(D$RPP1 location(-64185 -47795))
device(D$RPP1 location(-82445 -34985))
device(D$RPP1 location(-63930 -34985))
device(D$RPP1 location(-63435 640))
device(D$RPP1 location(-63405 -3330))
device(D$RPP1 location(-63640 -11955))
device(D$RPP1 location(-63660 -16185))
device(D$RPP1 location(-63755 -20345))
device(D$RPP1 location(-63865 -26810))
device(D$RPP1 location(-63500 -7535))
device(D$RPP1 location(-82015 -7750))
device(D$RPP1 location(-100465 855))
device(D$RPP1 location(-81950 425))
device(D$RPP1 location(-100435 -3115))
device(D$RPP1 location(-100670 -11740))
device(D$RPP1 location(-100690 -15970))
device(D$RPP1 location(-100785 -20130))
device(D$RPP1 location(-100785 -26915))
device(D$RPP1 location(-100530 -7320))
connect(4 A B)
connect(10 A B)
connect(16 A B)
connect(21 B B)
location(110140 51795)
param(R 95)
param(L 420)
param(W 2.21052631579)
param(A 1080)
param(P 1296)
terminal(A 1)
terminal(B 2)
)
)
)
# Reference netlist
reference(
# Device class section
class(RPP1 RES)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(RES2
# Nets
net(1 name(GND))
net(2 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(GND))
pin(2 name(VDD))
# Devices and their connections
device(1 RPP1
name(I0.I106.R0)
param(R 59475.7)
param(L 420)
param(W 2.21052631579)
param(A 0)
param(P 0)
terminal(A 2)
terminal(B 1)
)
)
)
# Cross reference
xref(
circuit(Res2 RES2 match
xref(
net(1 1 warning)
net(2 2 warning)
pin(() 0 match)
pin(() 1 match)
device(1 1 match)
)
)
)

7
testdata/lvs/res_combine2.cir vendored Normal file
View File

@ -0,0 +1,7 @@
* Extracted by KLayout
* cell Res2
.SUBCKT Res2
* device instance $1 r0 *1 110.14,51.795 RPP1
R$1 1 2 95 RPP1
.ENDS Res2

96
testdata/lvs/res_combine2.lvs vendored Normal file
View File

@ -0,0 +1,96 @@
source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("res_combine_schematic.cir")
deep
# -------------------------------------------------------------------
# Layers
pimp = input(7, 0)
poly_dg = input(13, 0)
cont = input(15, 0)
met1_dg = input(16, 0)
sblk = input(34, 0)
rp_1 = sblk & poly_dg
rpp1 = rp_1 & pimp
p1trm = poly_dg - rpp1
class ResistorExtractor < RBA::GenericDeviceExtractor
def initialize(name, sheet_rho)
self.name = name
@sheet_rho = sheet_rho
end
def setup
define_layer("C", "Conductor")
define_layer("R", "Resistor")
register_device_class(RBA::DeviceClassResistor::new)
end
def get_connectivity(layout, layers)
# this "connectivity" forms the shape clusters that make up the device
conn = RBA::Connectivity::new
conn.connect(layers[0], layers[1]) # collect touching contacts
conn.connect(layers[1], layers[1]) # combine resistor shapes into one area
conn
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are defined with "define_layer"
conductor = layer_geometry[0]
resistor = layer_geometry[1]
resistor_regions = resistor.merged
resistor_regions.each do |r|
terminals = conductor.interacting(resistor)
if terminals.size != 2
error("Resistor shape does not touch marker border in exactly two places", r)
else
double_width = 0
(terminals.edges & resistor.edges).merged.each do |e|
double_width += e.length
end
# A = L*W
# -> L = A/W
a = r.area*dbu*dbu
w = (double_width / 2.0)*dbu
l = a / w
device = create_device
device.set_parameter(RBA::DeviceClassResistor::PARAM_R, @sheet_rho * l / w);
device.set_parameter(RBA::DeviceClassResistor::PARAM_A, a)
device.set_parameter(RBA::DeviceClassResistor::PARAM_L, l)
device.set_parameter(RBA::DeviceClassResistor::PARAM_P, 2*l+2*w)
device.set_parameter(RBA::DeviceClassResistor::PARAM_W, w)
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_A, 0, terminals[0]);
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_B, 0, terminals[1]);
end
end
end
end
# tolerance/ignore
tolerance("RPP1", "W", 1e-5)
tolerance("RPP1", "L", 1e-5)
ignore_parameter("RPP1", "R")
extract_devices(ResistorExtractor::new("RPP1", 0.5), # intentionally wrong: 1565.15/5
{ "C" => p1trm, "R" => rpp1 })
connect(met1_dg, cont)
connect(p1trm, cont)
netlist.flatten_circuit("Res1")
schematic.flatten_circuit("RES1")
schematic.simplify
# Netlist vs. netlist
align
netlist.simplify
compare

193
testdata/lvs/res_combine2.lvsdb.1 vendored Normal file
View File

@ -0,0 +1,193 @@
#%lvsdb-klayout
# Layout
layout(
top(Res2)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l4 '15/0')
layer(l3 '16/0')
layer(l1)
# Mask layer connectivity
connect(l4 l4 l3 l1)
connect(l3 l4 l3)
connect(l1 l4 l1)
# Device class section
class(RPP1 RES)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$RPP1 RPP1
terminal(A
rect(l1 (0 0) (540 2000))
)
terminal(B
rect(l1 (10540 0) (540 2000))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(Res2
# Circuit boundary
rect((8285 720) (117975 57350))
# Nets with their geometries
net(1
rect(l4 (120580 32490) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-22355 1390) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-21520 1755) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (0 -4795) (1065 5850))
rect(l3 (-5155 -6930) (52985 1475))
rect(l3 (-27585 -395) (1065 5850))
rect(l3 (20990 -5850) (1065 5850))
rect(l3 (-1275 -1760) (340 1920))
rect(l3 (-22475 -1890) (340 1920))
rect(l3 (-21640 -1525) (340 1920))
rect(l1 (42935 -2385) (540 2000))
rect(l1 (-22675 -1970) (540 2000))
rect(l1 (-21840 -1605) (540 2000))
)
net(2
rect(l4 (19795 5575) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (-195 -995) (2395 2500))
rect(l3 (-2480 -1785) (340 1920))
rect(l1 (-500 -1960) (540 2000))
)
# Devices and their connections
device(1 D$RPP1
device(D$RPP1 location(30 -3970))
device(D$RPP1 location(-65 -8175))
device(D$RPP1 location(-205 -12595))
device(D$RPP1 location(-225 -16825))
device(D$RPP1 location(-320 -20985))
device(D$RPP1 location(-22135 30))
device(D$RPP1 location(-22105 -3940))
device(D$RPP1 location(-22200 -8145))
device(D$RPP1 location(-22340 -12565))
device(D$RPP1 location(-22360 -16795))
device(D$RPP1 location(-22455 -20955))
device(D$RPP1 location(-43435 425))
device(D$RPP1 location(-43405 -3545))
device(D$RPP1 location(-43500 -7750))
device(D$RPP1 location(-43640 -12170))
device(D$RPP1 location(-43660 -16400))
device(D$RPP1 location(-43755 -20560))
device(D$RPP1 location(-100755 -30885))
device(D$RPP1 location(-100850 -35090))
device(D$RPP1 location(-100990 -39510))
device(D$RPP1 location(-101010 -43740))
device(D$RPP1 location(-101105 -47900))
device(D$RPP1 location(-81920 -3545))
device(D$RPP1 location(-82015 -7750))
device(D$RPP1 location(-82155 -12170))
device(D$RPP1 location(-82175 -16400))
device(D$RPP1 location(-63835 -30780))
device(D$RPP1 location(-63930 -34985))
device(D$RPP1 location(-64070 -39405))
device(D$RPP1 location(-64090 -43635))
device(D$RPP1 location(-82380 -26810))
device(D$RPP1 location(-82270 -20560))
device(D$RPP1 location(-82350 -30780))
device(D$RPP1 location(-82445 -34985))
device(D$RPP1 location(-82585 -39405))
device(D$RPP1 location(-82605 -43635))
device(D$RPP1 location(-82700 -47795))
device(D$RPP1 location(-64185 -47795))
device(D$RPP1 location(-63435 640))
device(D$RPP1 location(-63405 -3330))
device(D$RPP1 location(-63500 -7535))
device(D$RPP1 location(-63640 -11955))
device(D$RPP1 location(-63660 -16185))
device(D$RPP1 location(-63755 -20345))
device(D$RPP1 location(-63865 -26810))
device(D$RPP1 location(-100465 855))
device(D$RPP1 location(-81950 425))
device(D$RPP1 location(-100435 -3115))
device(D$RPP1 location(-100530 -7320))
device(D$RPP1 location(-100670 -11740))
device(D$RPP1 location(-100690 -15970))
device(D$RPP1 location(-100785 -20130))
device(D$RPP1 location(-100785 -26915))
connect(5 A B)
connect(11 A B)
connect(17 A B)
connect(22 B B)
location(110140 51795)
param(R 95)
param(L 420)
param(W 2.21052631579)
param(A 1080)
param(P 1296)
terminal(A 1)
terminal(B 2)
)
)
)
# Reference netlist
reference(
# Device class section
class(RPP1 RES)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(RES2
# Nets
net(1 name(GND))
net(2 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(GND))
pin(2 name(VDD))
# Devices and their connections
device(1 RPP1
name(I0.I106.R0)
param(R 59475.7)
param(L 420)
param(W 2.21052631579)
param(A 0)
param(P 0)
terminal(A 2)
terminal(B 1)
)
)
)
# Cross reference
xref(
circuit(Res2 RES2 match
xref(
net(1 1 warning)
net(2 2 warning)
pin(() 0 match)
pin(() 1 match)
device(1 1 match)
)
)
)

193
testdata/lvs/res_combine2.lvsdb.2 vendored Normal file
View File

@ -0,0 +1,193 @@
#%lvsdb-klayout
# Layout
layout(
top(Res2)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l4 '15/0')
layer(l3 '16/0')
layer(l1)
# Mask layer connectivity
connect(l4 l4 l3 l1)
connect(l3 l4 l3)
connect(l1 l4 l1)
# Device class section
class(RPP1 RES)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$RPP1 RPP1
terminal(A
rect(l1 (0 0) (540 2000))
)
terminal(B
rect(l1 (10540 0) (540 2000))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(Res2
# Circuit boundary
rect((8285 720) (117975 57350))
# Nets with their geometries
net(1
rect(l4 (120580 32490) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-22355 1390) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-21520 1755) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (0 -4795) (1065 5850))
rect(l3 (-5155 -6930) (52985 1475))
rect(l3 (-27585 -395) (1065 5850))
rect(l3 (20990 -5850) (1065 5850))
rect(l3 (-1275 -1760) (340 1920))
rect(l3 (-22475 -1890) (340 1920))
rect(l3 (-21640 -1525) (340 1920))
rect(l1 (42935 -2385) (540 2000))
rect(l1 (-22675 -1970) (540 2000))
rect(l1 (-21840 -1605) (540 2000))
)
net(2
rect(l4 (19795 5575) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (-195 -995) (2395 2500))
rect(l3 (-2480 -1785) (340 1920))
rect(l1 (-500 -1960) (540 2000))
)
# Devices and their connections
device(1 D$RPP1
device(D$RPP1 location(30 -3970))
device(D$RPP1 location(-205 -12595))
device(D$RPP1 location(-225 -16825))
device(D$RPP1 location(-320 -20985))
device(D$RPP1 location(-65 -8175))
device(D$RPP1 location(-22135 30))
device(D$RPP1 location(-22105 -3940))
device(D$RPP1 location(-22340 -12565))
device(D$RPP1 location(-22360 -16795))
device(D$RPP1 location(-22455 -20955))
device(D$RPP1 location(-22200 -8145))
device(D$RPP1 location(-43435 425))
device(D$RPP1 location(-43405 -3545))
device(D$RPP1 location(-43640 -12170))
device(D$RPP1 location(-43660 -16400))
device(D$RPP1 location(-43755 -20560))
device(D$RPP1 location(-43500 -7750))
device(D$RPP1 location(-100755 -30885))
device(D$RPP1 location(-100990 -39510))
device(D$RPP1 location(-101010 -43740))
device(D$RPP1 location(-101105 -47900))
device(D$RPP1 location(-100850 -35090))
device(D$RPP1 location(-81920 -3545))
device(D$RPP1 location(-82155 -12170))
device(D$RPP1 location(-82175 -16400))
device(D$RPP1 location(-63835 -30780))
device(D$RPP1 location(-64070 -39405))
device(D$RPP1 location(-64090 -43635))
device(D$RPP1 location(-82380 -26810))
device(D$RPP1 location(-82270 -20560))
device(D$RPP1 location(-82350 -30780))
device(D$RPP1 location(-82585 -39405))
device(D$RPP1 location(-82605 -43635))
device(D$RPP1 location(-82700 -47795))
device(D$RPP1 location(-64185 -47795))
device(D$RPP1 location(-82445 -34985))
device(D$RPP1 location(-63930 -34985))
device(D$RPP1 location(-63435 640))
device(D$RPP1 location(-63405 -3330))
device(D$RPP1 location(-63640 -11955))
device(D$RPP1 location(-63660 -16185))
device(D$RPP1 location(-63755 -20345))
device(D$RPP1 location(-63865 -26810))
device(D$RPP1 location(-63500 -7535))
device(D$RPP1 location(-82015 -7750))
device(D$RPP1 location(-100465 855))
device(D$RPP1 location(-81950 425))
device(D$RPP1 location(-100435 -3115))
device(D$RPP1 location(-100670 -11740))
device(D$RPP1 location(-100690 -15970))
device(D$RPP1 location(-100785 -20130))
device(D$RPP1 location(-100785 -26915))
device(D$RPP1 location(-100530 -7320))
connect(4 A B)
connect(10 A B)
connect(16 A B)
connect(21 B B)
location(110140 51795)
param(R 95)
param(L 420)
param(W 2.21052631579)
param(A 1080)
param(P 1296)
terminal(A 1)
terminal(B 2)
)
)
)
# Reference netlist
reference(
# Device class section
class(RPP1 RES)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(RES2
# Nets
net(1 name(GND))
net(2 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(GND))
pin(2 name(VDD))
# Devices and their connections
device(1 RPP1
name(I0.I106.R0)
param(R 59475.7)
param(L 420)
param(W 2.21052631579)
param(A 0)
param(P 0)
terminal(A 2)
terminal(B 1)
)
)
)
# Cross reference
xref(
circuit(Res2 RES2 match
xref(
net(1 1 warning)
net(2 2 warning)
pin(() 0 match)
pin(() 1 match)
device(1 1 match)
)
)
)

7
testdata/lvs/res_combine3.cir vendored Normal file
View File

@ -0,0 +1,7 @@
* Extracted by KLayout
* cell Res2
.SUBCKT Res2
* device instance $1 r0 *1 110.14,51.795 RPP1
R$1 1 2 95 RPP1
.ENDS Res2

91
testdata/lvs/res_combine3.lvs vendored Normal file
View File

@ -0,0 +1,91 @@
source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("res_combine_schematic.cir")
deep
# -------------------------------------------------------------------
# Layers
pimp = input(7, 0)
poly_dg = input(13, 0)
cont = input(15, 0)
met1_dg = input(16, 0)
sblk = input(34, 0)
rp_1 = sblk & poly_dg
rpp1 = rp_1 & pimp
p1trm = poly_dg - rpp1
class ResistorExtractor < RBA::GenericDeviceExtractor
def initialize(name, sheet_rho)
self.name = name
@sheet_rho = sheet_rho
end
def setup
define_layer("C", "Conductor")
define_layer("R", "Resistor")
register_device_class(RBA::DeviceClassResistor::new)
end
def get_connectivity(layout, layers)
# this "connectivity" forms the shape clusters that make up the device
conn = RBA::Connectivity::new
conn.connect(layers[0], layers[1]) # collect touching contacts
conn.connect(layers[1], layers[1]) # combine resistor shapes into one area
conn
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are defined with "define_layer"
conductor = layer_geometry[0]
resistor = layer_geometry[1]
resistor_regions = resistor.merged
resistor_regions.each do |r|
terminals = conductor.interacting(resistor)
if terminals.size != 2
error("Resistor shape does not touch marker border in exactly two places", r)
else
double_width = 0
(terminals.edges & resistor.edges).merged.each do |e|
double_width += e.length
end
# A = L*W
# -> L = A/W
a = r.area*dbu*dbu
w = (double_width / 2.0)*dbu
l = a / w
device = create_device
device.set_parameter(RBA::DeviceClassResistor::PARAM_R, @sheet_rho * l / w);
device.set_parameter(RBA::DeviceClassResistor::PARAM_A, a)
device.set_parameter(RBA::DeviceClassResistor::PARAM_L, l)
device.set_parameter(RBA::DeviceClassResistor::PARAM_P, 2*l+2*w)
device.set_parameter(RBA::DeviceClassResistor::PARAM_W, w)
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_A, 0, terminals[0]);
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_B, 0, terminals[1]);
end
end
end
end
extract_devices(ResistorExtractor::new("RPP1", 0.5), # intentionally wrong: 1565.15/5
{ "C" => p1trm, "R" => rpp1 })
connect(met1_dg, cont)
connect(p1trm, cont)
netlist.flatten_circuit("Res1")
schematic.flatten_circuit("RES1")
schematic.simplify
# Netlist vs. netlist
align
netlist.simplify
compare

196
testdata/lvs/res_combine3.lvsdb.1 vendored Normal file
View File

@ -0,0 +1,196 @@
#%lvsdb-klayout
# Layout
layout(
top(Res2)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l4 '15/0')
layer(l3 '16/0')
layer(l1)
# Mask layer connectivity
connect(l4 l4 l3 l1)
connect(l3 l4 l3)
connect(l1 l4 l1)
# Device class section
class(RPP1 RES)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$RPP1 RPP1
terminal(A
rect(l1 (0 0) (540 2000))
)
terminal(B
rect(l1 (10540 0) (540 2000))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(Res2
# Circuit boundary
rect((8285 720) (117975 57350))
# Nets with their geometries
net(1
rect(l4 (120580 32490) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-22355 1390) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-21520 1755) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (0 -4795) (1065 5850))
rect(l3 (-5155 -6930) (52985 1475))
rect(l3 (-27585 -395) (1065 5850))
rect(l3 (20990 -5850) (1065 5850))
rect(l3 (-1275 -1760) (340 1920))
rect(l3 (-22475 -1890) (340 1920))
rect(l3 (-21640 -1525) (340 1920))
rect(l1 (42935 -2385) (540 2000))
rect(l1 (-22675 -1970) (540 2000))
rect(l1 (-21840 -1605) (540 2000))
)
net(2
rect(l4 (19795 5575) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (-195 -995) (2395 2500))
rect(l3 (-2480 -1785) (340 1920))
rect(l1 (-500 -1960) (540 2000))
)
# Devices and their connections
device(1 D$RPP1
device(D$RPP1 location(30 -3970))
device(D$RPP1 location(-65 -8175))
device(D$RPP1 location(-205 -12595))
device(D$RPP1 location(-225 -16825))
device(D$RPP1 location(-320 -20985))
device(D$RPP1 location(-22135 30))
device(D$RPP1 location(-22105 -3940))
device(D$RPP1 location(-22200 -8145))
device(D$RPP1 location(-22340 -12565))
device(D$RPP1 location(-22360 -16795))
device(D$RPP1 location(-22455 -20955))
device(D$RPP1 location(-43435 425))
device(D$RPP1 location(-43405 -3545))
device(D$RPP1 location(-43500 -7750))
device(D$RPP1 location(-43640 -12170))
device(D$RPP1 location(-43660 -16400))
device(D$RPP1 location(-43755 -20560))
device(D$RPP1 location(-100755 -30885))
device(D$RPP1 location(-100850 -35090))
device(D$RPP1 location(-100990 -39510))
device(D$RPP1 location(-101010 -43740))
device(D$RPP1 location(-101105 -47900))
device(D$RPP1 location(-81920 -3545))
device(D$RPP1 location(-82015 -7750))
device(D$RPP1 location(-82155 -12170))
device(D$RPP1 location(-82175 -16400))
device(D$RPP1 location(-63835 -30780))
device(D$RPP1 location(-63930 -34985))
device(D$RPP1 location(-64070 -39405))
device(D$RPP1 location(-64090 -43635))
device(D$RPP1 location(-82380 -26810))
device(D$RPP1 location(-82270 -20560))
device(D$RPP1 location(-82350 -30780))
device(D$RPP1 location(-82445 -34985))
device(D$RPP1 location(-82585 -39405))
device(D$RPP1 location(-82605 -43635))
device(D$RPP1 location(-82700 -47795))
device(D$RPP1 location(-64185 -47795))
device(D$RPP1 location(-63435 640))
device(D$RPP1 location(-63405 -3330))
device(D$RPP1 location(-63500 -7535))
device(D$RPP1 location(-63640 -11955))
device(D$RPP1 location(-63660 -16185))
device(D$RPP1 location(-63755 -20345))
device(D$RPP1 location(-63865 -26810))
device(D$RPP1 location(-100465 855))
device(D$RPP1 location(-81950 425))
device(D$RPP1 location(-100435 -3115))
device(D$RPP1 location(-100530 -7320))
device(D$RPP1 location(-100670 -11740))
device(D$RPP1 location(-100690 -15970))
device(D$RPP1 location(-100785 -20130))
device(D$RPP1 location(-100785 -26915))
connect(5 A B)
connect(11 A B)
connect(17 A B)
connect(22 B B)
location(110140 51795)
param(R 95)
param(L 420)
param(W 2.21052631579)
param(A 1080)
param(P 1296)
terminal(A 1)
terminal(B 2)
)
)
)
# Reference netlist
reference(
# Device class section
class(RPP1 RES)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(RES2
# Nets
net(1 name(GND))
net(2 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(GND))
pin(2 name(VDD))
# Devices and their connections
device(1 RPP1
name(I0.I106.R0)
param(R 59475.7)
param(L 420)
param(W 2.21052631579)
param(A 0)
param(P 0)
terminal(A 2)
terminal(B 1)
)
)
)
# Cross reference
xref(
circuit(Res2 RES2 nomatch
xref(
net(() 1 mismatch)
net(() 2 mismatch)
net(1 () mismatch)
net(2 () mismatch)
pin(() 0 match)
pin(() 1 match)
device(() 1 mismatch)
device(1 () mismatch)
)
)
)

196
testdata/lvs/res_combine3.lvsdb.2 vendored Normal file
View File

@ -0,0 +1,196 @@
#%lvsdb-klayout
# Layout
layout(
top(Res2)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l4 '15/0')
layer(l3 '16/0')
layer(l1)
# Mask layer connectivity
connect(l4 l4 l3 l1)
connect(l3 l4 l3)
connect(l1 l4 l1)
# Device class section
class(RPP1 RES)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$RPP1 RPP1
terminal(A
rect(l1 (0 0) (540 2000))
)
terminal(B
rect(l1 (10540 0) (540 2000))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(Res2
# Circuit boundary
rect((8285 720) (117975 57350))
# Nets with their geometries
net(1
rect(l4 (120580 32490) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-22355 1390) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l4 (-21520 1755) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (0 -4795) (1065 5850))
rect(l3 (-5155 -6930) (52985 1475))
rect(l3 (-27585 -395) (1065 5850))
rect(l3 (20990 -5850) (1065 5850))
rect(l3 (-1275 -1760) (340 1920))
rect(l3 (-22475 -1890) (340 1920))
rect(l3 (-21640 -1525) (340 1920))
rect(l1 (42935 -2385) (540 2000))
rect(l1 (-22675 -1970) (540 2000))
rect(l1 (-21840 -1605) (540 2000))
)
net(2
rect(l4 (19795 5575) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -745) (220 220))
rect(l4 (-220 -750) (220 220))
rect(l3 (-195 -995) (2395 2500))
rect(l3 (-2480 -1785) (340 1920))
rect(l1 (-500 -1960) (540 2000))
)
# Devices and their connections
device(1 D$RPP1
device(D$RPP1 location(30 -3970))
device(D$RPP1 location(-205 -12595))
device(D$RPP1 location(-225 -16825))
device(D$RPP1 location(-320 -20985))
device(D$RPP1 location(-65 -8175))
device(D$RPP1 location(-22135 30))
device(D$RPP1 location(-22105 -3940))
device(D$RPP1 location(-22340 -12565))
device(D$RPP1 location(-22360 -16795))
device(D$RPP1 location(-22455 -20955))
device(D$RPP1 location(-22200 -8145))
device(D$RPP1 location(-43435 425))
device(D$RPP1 location(-43405 -3545))
device(D$RPP1 location(-43640 -12170))
device(D$RPP1 location(-43660 -16400))
device(D$RPP1 location(-43755 -20560))
device(D$RPP1 location(-43500 -7750))
device(D$RPP1 location(-100755 -30885))
device(D$RPP1 location(-100990 -39510))
device(D$RPP1 location(-101010 -43740))
device(D$RPP1 location(-101105 -47900))
device(D$RPP1 location(-100850 -35090))
device(D$RPP1 location(-81920 -3545))
device(D$RPP1 location(-82155 -12170))
device(D$RPP1 location(-82175 -16400))
device(D$RPP1 location(-63835 -30780))
device(D$RPP1 location(-64070 -39405))
device(D$RPP1 location(-64090 -43635))
device(D$RPP1 location(-82380 -26810))
device(D$RPP1 location(-82270 -20560))
device(D$RPP1 location(-82350 -30780))
device(D$RPP1 location(-82585 -39405))
device(D$RPP1 location(-82605 -43635))
device(D$RPP1 location(-82700 -47795))
device(D$RPP1 location(-64185 -47795))
device(D$RPP1 location(-82445 -34985))
device(D$RPP1 location(-63930 -34985))
device(D$RPP1 location(-63435 640))
device(D$RPP1 location(-63405 -3330))
device(D$RPP1 location(-63640 -11955))
device(D$RPP1 location(-63660 -16185))
device(D$RPP1 location(-63755 -20345))
device(D$RPP1 location(-63865 -26810))
device(D$RPP1 location(-63500 -7535))
device(D$RPP1 location(-82015 -7750))
device(D$RPP1 location(-100465 855))
device(D$RPP1 location(-81950 425))
device(D$RPP1 location(-100435 -3115))
device(D$RPP1 location(-100670 -11740))
device(D$RPP1 location(-100690 -15970))
device(D$RPP1 location(-100785 -20130))
device(D$RPP1 location(-100785 -26915))
device(D$RPP1 location(-100530 -7320))
connect(4 A B)
connect(10 A B)
connect(16 A B)
connect(21 B B)
location(110140 51795)
param(R 95)
param(L 420)
param(W 2.21052631579)
param(A 1080)
param(P 1296)
terminal(A 1)
terminal(B 2)
)
)
)
# Reference netlist
reference(
# Device class section
class(RPP1 RES)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(RES2
# Nets
net(1 name(GND))
net(2 name(VDD))
# Outgoing pins and their connections to nets
pin(1 name(GND))
pin(2 name(VDD))
# Devices and their connections
device(1 RPP1
name(I0.I106.R0)
param(R 59475.7)
param(L 420)
param(W 2.21052631579)
param(A 0)
param(P 0)
terminal(A 2)
terminal(B 1)
)
)
)
# Cross reference
xref(
circuit(Res2 RES2 nomatch
xref(
net(() 1 mismatch)
net(() 2 mismatch)
net(1 () mismatch)
net(2 () mismatch)
pin(() 0 match)
pin(() 1 match)
device(() 1 mismatch)
device(1 () mismatch)
)
)
)

31
testdata/lvs/res_combine_schematic.cir vendored Normal file
View File

@ -0,0 +1,31 @@
.SUBCKT res1 MINUS PLUS
*.PININFO MINUS:B PLUS:B
RR7 net5 net3 1565.15 RPP1 W=2u L=10u M=1
RR8 net3 net6 1565.15 RPP1 W=2u L=10u M=1
RR9 net6 net7 1565.15 RPP1 W=2u L=10u M=1
RR10 net7 MINUS 1565.15 RPP1 W=2u L=10u M=1
RR6 net4 net5 1565.15 RPP1 W=2u L=10u M=1
RR0 PLUS net4 1565.15 RPP1 W=2u L=10u M=1
.ENDS
.SUBCKT res2_ MINUS PLUS
*.PININFO MINUS:B PLUS:B
XI106 net3 PLUS res1
XI104 net7 net8 res1
XI100 net6 MINUS res1
XI105 net3 net7 res1
XI107 net3 PLUS res1
XI108 net3 PLUS res1
XI101 net9 net6 res1
XI102 net10 net9 res1
XI103 net8 net10 res1
.ENDS
.SUBCKT Res2 gnd vdd
*.PININFO gnd:B vdd:B
XI0 gnd vdd res2_
.ENDS

View File

@ -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")