mirror of https://github.com/KLayout/klayout.git
commit
32254ffdca
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> ¶meter_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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1168,6 +1168,19 @@ END
|
|||
|
||||
end
|
||||
|
||||
def test_15_deviceParameterCompare
|
||||
|
||||
dpc = RBA::EqualDeviceParameters::new(1)
|
||||
assert_equal(dpc.to_string, "#1:A0/R0")
|
||||
|
||||
dpc += RBA::EqualDeviceParameters::new(2, 1.0, 0.25)
|
||||
assert_equal(dpc.to_string, "#1:A0/R0;#2:A1/R0.25")
|
||||
|
||||
dpc += RBA::EqualDeviceParameters::ignore(3)
|
||||
assert_equal(dpc.to_string, "#1:A0/R0;#2:A1/R0.25;#3:ignore")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue