mirror of https://github.com/KLayout/klayout.git
Fixed #806: first, the internal error gone. Second, the implementation of custom comparers is simplified as the 'equals' method does not need to be implemented.
This commit is contained in:
parent
ef22ead019
commit
fcb966393a
|
|
@ -79,18 +79,6 @@ bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) cons
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EqualDeviceParameters::equal (const db::Device &a, const db::Device &b) const
|
|
||||||
{
|
|
||||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = m_compare_set.begin (); c != m_compare_set.end (); ++c) {
|
|
||||||
int cmp = compare_parameters (a.parameter_value (c->first), b.parameter_value (c->first), c->second.first, c->second.second);
|
|
||||||
if (cmp != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
EqualDeviceParameters &EqualDeviceParameters::operator+= (const EqualDeviceParameters &other)
|
EqualDeviceParameters &EqualDeviceParameters::operator+= (const EqualDeviceParameters &other)
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = other.m_compare_set.begin (); c != other.m_compare_set.end (); ++c) {
|
for (std::vector<std::pair<size_t, std::pair<double, double> > >::const_iterator c = other.m_compare_set.begin (); c != other.m_compare_set.end (); ++c) {
|
||||||
|
|
@ -121,19 +109,6 @@ bool AllDeviceParametersAreEqual::less (const db::Device &a, const db::Device &b
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllDeviceParametersAreEqual::equal (const db::Device &a, const db::Device &b) const
|
|
||||||
{
|
|
||||||
const std::vector<db::DeviceParameterDefinition> ¶meters = a.device_class ()->parameter_definitions ();
|
|
||||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator c = parameters.begin (); c != parameters.end (); ++c) {
|
|
||||||
int cmp = compare_parameters (a.parameter_value (c->id ()), b.parameter_value (c->id ()), 0.0, m_relative);
|
|
||||||
if (cmp != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
// DeviceClass class implementation
|
// DeviceClass class implementation
|
||||||
|
|
||||||
|
|
@ -293,7 +268,7 @@ bool DeviceClass::equal (const db::Device &a, const db::Device &b)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcd != 0) {
|
if (pcd != 0) {
|
||||||
return pcd->equal (a, b);
|
return ! pcd->less (a, b) && ! pcd->less (b, a);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const std::vector<db::DeviceParameterDefinition> &pd = a.device_class ()->parameter_definitions ();
|
const std::vector<db::DeviceParameterDefinition> &pd = a.device_class ()->parameter_definitions ();
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,6 @@ public:
|
||||||
|
|
||||||
virtual DeviceParameterCompareDelegate *clone () const = 0;
|
virtual DeviceParameterCompareDelegate *clone () const = 0;
|
||||||
virtual bool less (const db::Device &a, const db::Device &b) const = 0;
|
virtual bool less (const db::Device &a, const db::Device &b) const = 0;
|
||||||
virtual bool equal (const db::Device &a, const db::Device &b) const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -315,7 +314,6 @@ public:
|
||||||
EqualDeviceParameters (size_t parameter_id, double relative, double absolute);
|
EqualDeviceParameters (size_t parameter_id, double relative, double absolute);
|
||||||
|
|
||||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||||
virtual bool equal (const db::Device &a, const db::Device &b) const;
|
|
||||||
|
|
||||||
virtual DeviceParameterCompareDelegate *clone () const
|
virtual DeviceParameterCompareDelegate *clone () const
|
||||||
{
|
{
|
||||||
|
|
@ -345,7 +343,6 @@ public:
|
||||||
AllDeviceParametersAreEqual (double relative);
|
AllDeviceParametersAreEqual (double relative);
|
||||||
|
|
||||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||||
virtual bool equal (const db::Device &a, const db::Device &b) const;
|
|
||||||
|
|
||||||
virtual DeviceParameterCompareDelegate *clone () const
|
virtual DeviceParameterCompareDelegate *clone () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3052,7 +3052,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
db::DeviceClass *db = const_cast<db::DeviceClass *> (i->second.second);
|
db::DeviceClass *db = const_cast<db::DeviceClass *> (i->second.second);
|
||||||
|
|
||||||
const db::DeviceParameterCompareDelegate *cmp = da->parameter_compare_delegate ();
|
const db::DeviceParameterCompareDelegate *cmp = da->parameter_compare_delegate ();
|
||||||
db->set_parameter_compare_delegate (cmp ? cmp->clone () : 0);
|
db->set_parameter_compare_delegate (const_cast<db::DeviceParameterCompareDelegate *> (cmp));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -843,15 +843,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool equal (const db::Device &a, const db::Device &b) const
|
|
||||||
{
|
|
||||||
if (cb_equal.can_issue ()) {
|
|
||||||
return cb_equal.issue<db::EqualDeviceParameters, bool, const db::Device &, const db::Device &> (&db::EqualDeviceParameters::equal, a, b);
|
|
||||||
} else {
|
|
||||||
return db::EqualDeviceParameters::equal (a, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gsi::Callback cb_less, cb_equal;
|
gsi::Callback cb_less, cb_equal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -903,13 +894,12 @@ Class<db::EqualDeviceParameters> decl_dbEqualDeviceParameters ("db", "EqualDevic
|
||||||
);
|
);
|
||||||
|
|
||||||
Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_dbEqualDeviceParameters, "db", "GenericDeviceParameterCompare",
|
Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_dbEqualDeviceParameters, "db", "GenericDeviceParameterCompare",
|
||||||
gsi::callback ("equal", &GenericDeviceParameterCompare::equal, &GenericDeviceParameterCompare::cb_equal, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
|
||||||
"@brief Compares the parameters of two devices for equality. "
|
|
||||||
"Returns true, if the parameters of device a and b are considered equal."
|
|
||||||
) +
|
|
||||||
gsi::callback ("less", &GenericDeviceParameterCompare::less, &GenericDeviceParameterCompare::cb_less, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
gsi::callback ("less", &GenericDeviceParameterCompare::less, &GenericDeviceParameterCompare::cb_less, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
||||||
"@brief Compares the parameters of two devices for a begin less than b. "
|
"@brief Compares the parameters of two devices for a begin less than b. "
|
||||||
"Returns true, if the parameters of device a are considered less than those of device b."
|
"Returns true, if the parameters of device a are considered less than those of device b."
|
||||||
|
"The 'less' implementation needs to ensure strict weak ordering. Specifically, less(a,b) == false and less(b,a) implies that a is equal to b and "
|
||||||
|
"less(a,b) == true implies that less(b,a) is false and vice versa. If not, an internal error "
|
||||||
|
"will be encountered on netlist compare."
|
||||||
),
|
),
|
||||||
"@brief A class implementing the comparison of device parameters.\n"
|
"@brief A class implementing the comparison of device parameters.\n"
|
||||||
"Reimplement this class to provide a custom device parameter compare scheme.\n"
|
"Reimplement this class to provide a custom device parameter compare scheme.\n"
|
||||||
|
|
@ -919,7 +909,7 @@ Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_db
|
||||||
"This class is intended for special cases. In most scenarios it is easier to use \\EqualDeviceParameters instead of "
|
"This class is intended for special cases. In most scenarios it is easier to use \\EqualDeviceParameters instead of "
|
||||||
"implementing a custom comparer class.\n"
|
"implementing a custom comparer class.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This class has been added in version 0.26."
|
"This class has been added in version 0.26. The 'equal' method has been dropped in 0.27.1 as it can be expressed as !less(a,b) && !less(b,a)."
|
||||||
);
|
);
|
||||||
|
|
||||||
static tl::id_type id_of_device_class (const db::DeviceClass *cls)
|
static tl::id_type id_of_device_class (const db::DeviceClass *cls)
|
||||||
|
|
|
||||||
|
|
@ -206,3 +206,8 @@ TEST(23_issue709)
|
||||||
run_test (_this, "empty_subcells", "empty_subcells.gds");
|
run_test (_this, "empty_subcells", "empty_subcells.gds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// empty gds
|
||||||
|
TEST(24_issue806)
|
||||||
|
{
|
||||||
|
run_test (_this, "custom_compare", "custom_compare.gds");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
* Extracted by KLayout
|
||||||
|
|
||||||
|
* cell TOP
|
||||||
|
.SUBCKT TOP
|
||||||
|
* device instance $1 r0 *1 7.52,4.175 RES
|
||||||
|
R$1 2 1 51 RES
|
||||||
|
.ENDS TOP
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
source($lvs_test_source)
|
||||||
|
report_lvs($lvs_test_target_lvsdb, true)
|
||||||
|
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
|
||||||
|
|
||||||
|
schematic("custom_compare_sch.cir")
|
||||||
|
|
||||||
|
deep
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Layers
|
||||||
|
|
||||||
|
# Drawing layers
|
||||||
|
nwell = input(1, 0)
|
||||||
|
active = input(2, 0)
|
||||||
|
pplus = input(3, 0)
|
||||||
|
nplus = input(4, 0)
|
||||||
|
poly = input(5, 0)
|
||||||
|
thickox = input(6, 0)
|
||||||
|
polyres = input(7, 0)
|
||||||
|
contact = input(8, 0)
|
||||||
|
metal1 = input(9, 0) # includes labels
|
||||||
|
via1 = input(10, 0)
|
||||||
|
metal2 = input(11, 0) # includes labels
|
||||||
|
|
||||||
|
# Bulk layer for terminal provisioning
|
||||||
|
bulk = polygon_layer
|
||||||
|
|
||||||
|
# Computed layers
|
||||||
|
poly_not_res = poly - polyres
|
||||||
|
poly_in_res = poly & polyres
|
||||||
|
|
||||||
|
# Resistor Definition
|
||||||
|
res_ex = resistor("RES", 1.0)
|
||||||
|
extract_devices(res_ex, { "C" => poly_not_res, "R" => poly_in_res })
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Connectivity
|
||||||
|
|
||||||
|
# Inter-layer
|
||||||
|
connect(poly_not_res, contact)
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Netlist and compare
|
||||||
|
|
||||||
|
class ResistorComparator < RBA::GenericDeviceParameterCompare
|
||||||
|
|
||||||
|
def less(device_a, device_b)
|
||||||
|
delta = 1
|
||||||
|
param_id = RBA::DeviceClassResistor::PARAM_R
|
||||||
|
param = "R"
|
||||||
|
if (device_a.parameter(param_id) - device_b.parameter(param_id)).abs > delta
|
||||||
|
result = device_a.parameter(param_id) < device_b.parameter(param_id)
|
||||||
|
return result
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
netlist.device_class_by_name("RES").equal_parameters = ResistorComparator::new()
|
||||||
|
|
||||||
|
# Netlist normalization
|
||||||
|
netlist.simplify
|
||||||
|
|
||||||
|
# Hierarchy alignment (flatten out unmatched cells)
|
||||||
|
align
|
||||||
|
|
||||||
|
# Netlist vs. netlist
|
||||||
|
compare
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
#%lvsdb-klayout
|
||||||
|
|
||||||
|
# Layout
|
||||||
|
layout(
|
||||||
|
top(TOP)
|
||||||
|
unit(0.001)
|
||||||
|
|
||||||
|
# Layer section
|
||||||
|
# This section lists the mask layers (drawing or derived) and their connections.
|
||||||
|
|
||||||
|
# Mask layers
|
||||||
|
layer(l3 '8/0')
|
||||||
|
layer(l1)
|
||||||
|
|
||||||
|
# Mask layer connectivity
|
||||||
|
connect(l3 l3 l1)
|
||||||
|
connect(l1 l3 l1)
|
||||||
|
|
||||||
|
# Device class section
|
||||||
|
class(RES RES)
|
||||||
|
|
||||||
|
# Device abstracts section
|
||||||
|
# Device abstracts list the pin shapes of the devices.
|
||||||
|
device(D$RES RES
|
||||||
|
terminal(A
|
||||||
|
rect(l1 (2225 -675) (200 250))
|
||||||
|
)
|
||||||
|
terminal(B
|
||||||
|
rect(l1 (-2425 425) (200 250))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Circuit section
|
||||||
|
# Circuits are the hierarchical building blocks of the netlist.
|
||||||
|
circuit(TOP
|
||||||
|
|
||||||
|
# Circuit boundary
|
||||||
|
rect((0 0) (10255 5900))
|
||||||
|
|
||||||
|
# Nets with their geometries
|
||||||
|
net(1
|
||||||
|
rect(l3 (4850 4600) (180 180))
|
||||||
|
rect(l1 (-245 -250) (310 320))
|
||||||
|
rect(l1 (0 -250) (200 250))
|
||||||
|
)
|
||||||
|
net(2
|
||||||
|
rect(l3 (10010 3500) (180 180))
|
||||||
|
rect(l1 (-245 -250) (310 320))
|
||||||
|
rect(l1 (-510 -250) (200 250))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Devices and their connections
|
||||||
|
device(1 D$RES
|
||||||
|
location(7520 4175)
|
||||||
|
param(R 51)
|
||||||
|
param(L 25.5)
|
||||||
|
param(W 0.5)
|
||||||
|
param(A 3.1875)
|
||||||
|
param(P 26)
|
||||||
|
terminal(A 2)
|
||||||
|
terminal(B 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Reference netlist
|
||||||
|
reference(
|
||||||
|
|
||||||
|
# Device class section
|
||||||
|
class(RES RES)
|
||||||
|
|
||||||
|
# Circuit section
|
||||||
|
# Circuits are the hierarchical building blocks of the netlist.
|
||||||
|
circuit(TOP
|
||||||
|
|
||||||
|
# Nets
|
||||||
|
net(1 name(R1))
|
||||||
|
net(2 name(R2))
|
||||||
|
|
||||||
|
# Outgoing pins and their connections to nets
|
||||||
|
pin(1 name(R1))
|
||||||
|
pin(2 name(R2))
|
||||||
|
|
||||||
|
# Devices and their connections
|
||||||
|
device(1 RES
|
||||||
|
name('5')
|
||||||
|
param(R 50.1)
|
||||||
|
param(L 0)
|
||||||
|
param(W 0)
|
||||||
|
param(A 0)
|
||||||
|
param(P 0)
|
||||||
|
terminal(A 1)
|
||||||
|
terminal(B 2)
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Cross reference
|
||||||
|
xref(
|
||||||
|
circuit(TOP TOP match
|
||||||
|
xref(
|
||||||
|
net(1 1 warning)
|
||||||
|
net(2 2 warning)
|
||||||
|
pin(() 0 match)
|
||||||
|
pin(() 1 match)
|
||||||
|
device(1 1 match)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
.subckt top r1 r2
|
||||||
|
r5 r1 r2 50.1
|
||||||
|
.ends
|
||||||
Loading…
Reference in New Issue