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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -293,7 +268,7 @@ bool DeviceClass::equal (const db::Device &a, const db::Device &b)
|
|||
}
|
||||
|
||||
if (pcd != 0) {
|
||||
return pcd->equal (a, b);
|
||||
return ! pcd->less (a, b) && ! pcd->less (b, a);
|
||||
} else {
|
||||
|
||||
const std::vector<db::DeviceParameterDefinition> &pd = a.device_class ()->parameter_definitions ();
|
||||
|
|
|
|||
|
|
@ -297,7 +297,6 @@ public:
|
|||
|
||||
virtual DeviceParameterCompareDelegate *clone () 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);
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -345,7 +343,6 @@ public:
|
|||
AllDeviceParametersAreEqual (double relative);
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
@ -903,13 +894,12 @@ Class<db::EqualDeviceParameters> decl_dbEqualDeviceParameters ("db", "EqualDevic
|
|||
);
|
||||
|
||||
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"),
|
||||
"@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."
|
||||
"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"
|
||||
"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 "
|
||||
"implementing a custom comparer class.\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)
|
||||
|
|
|
|||
|
|
@ -206,3 +206,8 @@ TEST(23_issue709)
|
|||
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