mirror of https://github.com/KLayout/klayout.git
Merge pull request #1851 from KLayout/bugfix/issue-1832
Bugfix/issue 1832
This commit is contained in:
commit
2d57feeae8
|
|
@ -825,6 +825,41 @@ void Circuit::do_purge_nets (bool keep_pins)
|
|||
}
|
||||
}
|
||||
|
||||
static bool can_purge_device (const db::Device &device)
|
||||
{
|
||||
if (! device.device_class ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<db::DeviceTerminalDefinition> &tdefs = device.device_class ()->terminal_definitions ();
|
||||
if (tdefs.size () <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const db::Net *net = device.net_for_terminal (tdefs.front ().id ());
|
||||
for (auto t = tdefs.begin () + 1; t != tdefs.end (); ++t) {
|
||||
if (net != device.net_for_terminal (t->id ())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Circuit::purge_devices ()
|
||||
{
|
||||
std::vector<db::Device *> devices_to_be_purged;
|
||||
for (device_iterator d = begin_devices (); d != end_devices (); ++d) {
|
||||
if (can_purge_device (*d)) {
|
||||
devices_to_be_purged.push_back (d.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto d = devices_to_be_purged.begin (); d != devices_to_be_purged.end (); ++d) {
|
||||
remove_device (*d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sanity check for device to be removed
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -732,6 +732,14 @@ public:
|
|||
*/
|
||||
void purge_nets_keep_pins ();
|
||||
|
||||
/**
|
||||
* @brief Purges invalid devices
|
||||
*
|
||||
* This method will purge all invalid devices, i.e. those
|
||||
* whose terminals are all connected to the same net.
|
||||
*/
|
||||
void purge_devices ();
|
||||
|
||||
/**
|
||||
* @brief Combine devices
|
||||
*
|
||||
|
|
|
|||
|
|
@ -619,6 +619,13 @@ void Netlist::purge_nets ()
|
|||
}
|
||||
}
|
||||
|
||||
void Netlist::purge_devices ()
|
||||
{
|
||||
for (bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up (); ++c) {
|
||||
c->purge_devices ();
|
||||
}
|
||||
}
|
||||
|
||||
void Netlist::make_top_level_pins ()
|
||||
{
|
||||
size_t ntop = top_circuit_count ();
|
||||
|
|
@ -684,6 +691,8 @@ void Netlist::simplify ()
|
|||
{
|
||||
make_top_level_pins ();
|
||||
purge ();
|
||||
|
||||
// combine devices are purge nets that are created in that step
|
||||
combine_devices ();
|
||||
purge_nets ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -508,6 +508,14 @@ public:
|
|||
*/
|
||||
void purge_nets ();
|
||||
|
||||
/**
|
||||
* @brief Purges invalid devices
|
||||
*
|
||||
* This method will purge all invalid devices, i.e. those
|
||||
* whose terminals are all connected to the same net.
|
||||
*/
|
||||
void purge_devices ();
|
||||
|
||||
/**
|
||||
* @brief Creates pins for top-level circuits
|
||||
*
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ public:
|
|||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
a->set_parameter_value (0, va + vb < 1e-30 ? 0.0 : va * vb / (va + vb));
|
||||
|
||||
// parallel width is sum of both, length is the one that gives the same value of resistance
|
||||
// R = 1/(1/R1 + 1/R2)
|
||||
|
|
@ -204,7 +204,7 @@ public:
|
|||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
a->set_parameter_value (0, va + vb < 1e-30 ? 0.0 : va * vb / (va + vb));
|
||||
|
||||
// TODO: does this implementation make sense?
|
||||
double aa = a->parameter_value (1);
|
||||
|
|
@ -259,7 +259,7 @@ public:
|
|||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
a->set_parameter_value (0, va + vb < 1e-30 ? 0.0 : va * vb / (va + vb));
|
||||
}
|
||||
|
||||
void serial (Device *a, Device *b) const
|
||||
|
|
|
|||
|
|
@ -1809,6 +1809,12 @@ Class<db::Circuit> decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit",
|
|||
"For example, serial or parallel resistors can be combined into "
|
||||
"a single resistor.\n"
|
||||
) +
|
||||
gsi::method ("purge_devices", &db::Circuit::purge_devices,
|
||||
"@brief Purges invalid devices.\n"
|
||||
"Purges devices which are considered invalid. Such devices are for example those whose terminals are all connected to a single net.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.29.7."
|
||||
) +
|
||||
gsi::method ("purge_nets", &db::Circuit::purge_nets,
|
||||
"@brief Purges floating nets.\n"
|
||||
"Floating nets are nets with no device or subcircuit attached to. Such floating "
|
||||
|
|
@ -2176,6 +2182,12 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
|
|||
"Floating nets can be created as effect of reconnections of devices or pins. "
|
||||
"This method will eliminate all nets that make less than two connections."
|
||||
) +
|
||||
gsi::method ("purge_devices", &db::Netlist::purge_devices,
|
||||
"@brief Purges invalid devices.\n"
|
||||
"Purges devices which are considered invalid. Such devices are for example those whose terminals are all connected to a single net.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.29.7."
|
||||
) +
|
||||
gsi::method ("simplify", &db::Netlist::simplify,
|
||||
"@brief Convenience method that combines the simplification.\n"
|
||||
"This method is a convenience method that runs \\make_top_level_pins, \\purge, \\combine_devices and \\purge_nets."
|
||||
|
|
|
|||
|
|
@ -1792,3 +1792,253 @@ TEST(26_JoinNets)
|
|||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
// Issue #1832 - small caps are not combined properly
|
||||
TEST(27_CombineSmallC)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
db::Circuit *circuit = new db::Circuit ();
|
||||
circuit->set_name ("TOP");
|
||||
nl.add_circuit (circuit);
|
||||
|
||||
db::DeviceClass *device = new db::DeviceClassCapacitor ();
|
||||
device->set_name ("model_name");
|
||||
nl.add_device_class (device);
|
||||
|
||||
db::Net *n1 = new db::Net ("n1");
|
||||
circuit->add_net (n1);
|
||||
|
||||
db::Net *n2 = new db::Net ("n2");
|
||||
circuit->add_net (n2);
|
||||
|
||||
db::Net *n3 = new db::Net ("n3");
|
||||
circuit->add_net (n3);
|
||||
|
||||
auto p1 = circuit->add_pin ("p1");
|
||||
auto p2 = circuit->add_pin ("p2");
|
||||
|
||||
circuit->connect_pin (p1.id (), n1);
|
||||
circuit->connect_pin (p2.id (), n3);
|
||||
|
||||
db::Device *c1 = new db::Device (device, "c1");
|
||||
circuit->add_device (c1);
|
||||
c1->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 1e-15);
|
||||
|
||||
db::Device *c2 = new db::Device (device, "c2");
|
||||
circuit->add_device (c2);
|
||||
c2->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 2e-15);
|
||||
|
||||
db::Device *c3 = new db::Device (device, "c3");
|
||||
circuit->add_device (c3);
|
||||
c3->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 3e-15);
|
||||
|
||||
c1->connect_terminal (db::DeviceClassCapacitor::terminal_id_A, n1);
|
||||
c1->connect_terminal (db::DeviceClassCapacitor::terminal_id_B, n2);
|
||||
|
||||
c2->connect_terminal (db::DeviceClassCapacitor::terminal_id_A, n2);
|
||||
c2->connect_terminal (db::DeviceClassCapacitor::terminal_id_B, n3);
|
||||
|
||||
c3->connect_terminal (db::DeviceClassCapacitor::terminal_id_A, n1);
|
||||
c3->connect_terminal (db::DeviceClassCapacitor::terminal_id_B, n3);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n3);\n"
|
||||
" device model_name c1 (A=n1,B=n2) (C=1e-15,A=0,P=0);\n"
|
||||
" device model_name c2 (A=n2,B=n3) (C=2e-15,A=0,P=0);\n"
|
||||
" device model_name c3 (A=n1,B=n3) (C=3e-15,A=0,P=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
nl.combine_devices ();
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n3);\n"
|
||||
" device model_name c1 (A=n1,B=n3) (C=3.66666666667e-15,A=0,P=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(27_CombineSmallR)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
db::Circuit *circuit = new db::Circuit ();
|
||||
circuit->set_name ("TOP");
|
||||
nl.add_circuit (circuit);
|
||||
|
||||
db::DeviceClass *device = new db::DeviceClassResistor ();
|
||||
device->set_name ("model_name");
|
||||
nl.add_device_class (device);
|
||||
|
||||
db::Net *n1 = new db::Net ("n1");
|
||||
circuit->add_net (n1);
|
||||
|
||||
db::Net *n2 = new db::Net ("n2");
|
||||
circuit->add_net (n2);
|
||||
|
||||
db::Net *n3 = new db::Net ("n3");
|
||||
circuit->add_net (n3);
|
||||
|
||||
auto p1 = circuit->add_pin ("p1");
|
||||
auto p2 = circuit->add_pin ("p2");
|
||||
|
||||
circuit->connect_pin (p1.id (), n1);
|
||||
circuit->connect_pin (p2.id (), n3);
|
||||
|
||||
db::Device *c1 = new db::Device (device, "c1");
|
||||
circuit->add_device (c1);
|
||||
c1->set_parameter_value (db::DeviceClassResistor::param_id_R, 1e-15);
|
||||
|
||||
db::Device *c2 = new db::Device (device, "c2");
|
||||
circuit->add_device (c2);
|
||||
c2->set_parameter_value (db::DeviceClassResistor::param_id_R, 2e-15);
|
||||
|
||||
db::Device *c3 = new db::Device (device, "c3");
|
||||
circuit->add_device (c3);
|
||||
c3->set_parameter_value (db::DeviceClassResistor::param_id_R, 3e-15);
|
||||
|
||||
c1->connect_terminal (db::DeviceClassResistor::terminal_id_A, n1);
|
||||
c1->connect_terminal (db::DeviceClassResistor::terminal_id_B, n2);
|
||||
|
||||
c2->connect_terminal (db::DeviceClassResistor::terminal_id_A, n2);
|
||||
c2->connect_terminal (db::DeviceClassResistor::terminal_id_B, n3);
|
||||
|
||||
c3->connect_terminal (db::DeviceClassResistor::terminal_id_A, n1);
|
||||
c3->connect_terminal (db::DeviceClassResistor::terminal_id_B, n3);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n3);\n"
|
||||
" device model_name c1 (A=n1,B=n2) (R=1e-15,L=0,W=0,A=0,P=0);\n"
|
||||
" device model_name c2 (A=n2,B=n3) (R=2e-15,L=0,W=0,A=0,P=0);\n"
|
||||
" device model_name c3 (A=n1,B=n3) (R=3e-15,L=0,W=0,A=0,P=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
nl.combine_devices ();
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n3);\n"
|
||||
" device model_name c1 (A=n1,B=n3) (R=1.5e-15,L=0,W=0,A=0,P=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(27_CombineSmallL)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
db::Circuit *circuit = new db::Circuit ();
|
||||
circuit->set_name ("TOP");
|
||||
nl.add_circuit (circuit);
|
||||
|
||||
db::DeviceClass *device = new db::DeviceClassInductor ();
|
||||
device->set_name ("model_name");
|
||||
nl.add_device_class (device);
|
||||
|
||||
db::Net *n1 = new db::Net ("n1");
|
||||
circuit->add_net (n1);
|
||||
|
||||
db::Net *n2 = new db::Net ("n2");
|
||||
circuit->add_net (n2);
|
||||
|
||||
db::Net *n3 = new db::Net ("n3");
|
||||
circuit->add_net (n3);
|
||||
|
||||
auto p1 = circuit->add_pin ("p1");
|
||||
auto p2 = circuit->add_pin ("p2");
|
||||
|
||||
circuit->connect_pin (p1.id (), n1);
|
||||
circuit->connect_pin (p2.id (), n3);
|
||||
|
||||
db::Device *c1 = new db::Device (device, "c1");
|
||||
circuit->add_device (c1);
|
||||
c1->set_parameter_value (db::DeviceClassInductor::param_id_L, 1e-15);
|
||||
|
||||
db::Device *c2 = new db::Device (device, "c2");
|
||||
circuit->add_device (c2);
|
||||
c2->set_parameter_value (db::DeviceClassInductor::param_id_L, 2e-15);
|
||||
|
||||
db::Device *c3 = new db::Device (device, "c3");
|
||||
circuit->add_device (c3);
|
||||
c3->set_parameter_value (db::DeviceClassInductor::param_id_L, 3e-15);
|
||||
|
||||
c1->connect_terminal (db::DeviceClassInductor::terminal_id_A, n1);
|
||||
c1->connect_terminal (db::DeviceClassInductor::terminal_id_B, n2);
|
||||
|
||||
c2->connect_terminal (db::DeviceClassInductor::terminal_id_A, n2);
|
||||
c2->connect_terminal (db::DeviceClassInductor::terminal_id_B, n3);
|
||||
|
||||
c3->connect_terminal (db::DeviceClassInductor::terminal_id_A, n1);
|
||||
c3->connect_terminal (db::DeviceClassInductor::terminal_id_B, n3);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n3);\n"
|
||||
" device model_name c1 (A=n1,B=n2) (L=1e-15);\n"
|
||||
" device model_name c2 (A=n2,B=n3) (L=2e-15);\n"
|
||||
" device model_name c3 (A=n1,B=n3) (L=3e-15);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
nl.combine_devices ();
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n3);\n"
|
||||
" device model_name c1 (A=n1,B=n3) (L=1.5e-15);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(28_EliminateShortedDevices)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
db::Circuit *circuit = new db::Circuit ();
|
||||
circuit->set_name ("TOP");
|
||||
nl.add_circuit (circuit);
|
||||
|
||||
db::DeviceClass *device = new db::DeviceClassCapacitor ();
|
||||
device->set_name ("model_name");
|
||||
nl.add_device_class (device);
|
||||
|
||||
db::Net *n1 = new db::Net ("n1");
|
||||
circuit->add_net (n1);
|
||||
|
||||
db::Net *n2 = new db::Net ("n2");
|
||||
circuit->add_net (n2);
|
||||
|
||||
auto p1 = circuit->add_pin ("p1");
|
||||
auto p2 = circuit->add_pin ("p2");
|
||||
|
||||
circuit->connect_pin (p1.id (), n1);
|
||||
circuit->connect_pin (p2.id (), n2);
|
||||
|
||||
db::Device *c1 = new db::Device (device, "c1");
|
||||
circuit->add_device (c1);
|
||||
c1->set_parameter_value (db::DeviceClassInductor::param_id_L, 1e-15);
|
||||
|
||||
db::Device *c2 = new db::Device (device, "c2");
|
||||
circuit->add_device (c2);
|
||||
c2->set_parameter_value (db::DeviceClassInductor::param_id_L, 2e-15);
|
||||
|
||||
c1->connect_terminal (db::DeviceClassInductor::terminal_id_A, n1);
|
||||
c1->connect_terminal (db::DeviceClassInductor::terminal_id_B, n1);
|
||||
|
||||
c2->connect_terminal (db::DeviceClassInductor::terminal_id_A, n1);
|
||||
c2->connect_terminal (db::DeviceClassInductor::terminal_id_B, n2);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n2);\n"
|
||||
" device model_name c1 (A=n1,B=n1) (C=1e-15,A=0,P=0);\n"
|
||||
" device model_name c2 (A=n1,B=n2) (C=2e-15,A=0,P=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
nl.purge_devices ();
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP (p1=n1,p2=n2);\n"
|
||||
" device model_name c2 (A=n1,B=n2) (C=2e-15,A=0,P=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,12 @@ TEST(12_private)
|
|||
run_test (_this, "test_12.lvs", "test_12b.cir.gz", "test_12.gds.gz", true);
|
||||
}
|
||||
|
||||
TEST(121_private)
|
||||
{
|
||||
// test_is_long_runner ();
|
||||
run_test (_this, "test_121.lvs", "test_121.cir.gz", "test_121.gds.gz", true);
|
||||
}
|
||||
|
||||
TEST(13_private)
|
||||
{
|
||||
// test_is_long_runner ();
|
||||
|
|
|
|||
Loading…
Reference in New Issue