diff --git a/src/db/db/dbNetlistDeviceClasses.cc b/src/db/db/dbNetlistDeviceClasses.cc index 232f4736d..c2357fd58 100644 --- a/src/db/db/dbNetlistDeviceClasses.cc +++ b/src/db/db/dbNetlistDeviceClasses.cc @@ -278,6 +278,7 @@ void DeviceClassInductor::serial (Device *a, Device *b) const // DeviceClassInductor implementation DB_PUBLIC size_t DeviceClassDiode::param_id_A = 0; +DB_PUBLIC size_t DeviceClassDiode::param_id_P = 1; DB_PUBLIC size_t DeviceClassDiode::terminal_id_A = 0; DB_PUBLIC size_t DeviceClassDiode::terminal_id_C = 1; @@ -288,6 +289,7 @@ DeviceClassDiode::DeviceClassDiode () add_terminal_definition (db::DeviceTerminalDefinition ("C", "Cathode")); add_parameter_definition (db::DeviceParameterDefinition ("A", "Area (square micrometer)", 0.0)); + add_parameter_definition (db::DeviceParameterDefinition ("P", "Perimeter (micrometer)", 0.0)); } bool DeviceClassDiode::combine_devices (Device *a, Device *b) const @@ -301,6 +303,7 @@ bool DeviceClassDiode::combine_devices (Device *a, Device *b) const if (na1 == nb1 && na2 == nb2) { a->set_parameter_value (0, a->parameter_value (0) + b->parameter_value (0)); + a->set_parameter_value (1, a->parameter_value (1) + b->parameter_value (1)); a->join_terminals (0, b, 0); a->join_terminals (1, b, 1); diff --git a/src/db/db/dbNetlistDeviceClasses.h b/src/db/db/dbNetlistDeviceClasses.h index fc90ef368..439ec7039 100644 --- a/src/db/db/dbNetlistDeviceClasses.h +++ b/src/db/db/dbNetlistDeviceClasses.h @@ -193,6 +193,7 @@ public: DeviceClassDiode (); static size_t param_id_A; + static size_t param_id_P; static size_t terminal_id_A; static size_t terminal_id_C; diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 8216eb425..b2b4218a0 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -521,7 +521,7 @@ Device *NetlistDeviceExtractor::create_device () return device; } -void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id, size_t layer_index, const db::Region ®ion) +void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id, size_t geometry_index, const db::Region ®ion) { tl_assert (mp_layout != 0); tl_assert (geometry_index < m_layers.size ()); diff --git a/src/db/db/dbNetlistDeviceExtractorClasses.cc b/src/db/db/dbNetlistDeviceExtractorClasses.cc index 08f2336c2..3f6d25b2e 100644 --- a/src/db/db/dbNetlistDeviceExtractorClasses.cc +++ b/src/db/db/dbNetlistDeviceExtractorClasses.cc @@ -504,4 +504,78 @@ void NetlistDeviceExtractorBipolarTransistor::extract_devices (const std::vector } } +// --------------------------------------------------------------------------------- +// NetlistDeviceExtractorDiode implementation + +NetlistDeviceExtractorDiode::NetlistDeviceExtractorDiode (const std::string &name) + : db::NetlistDeviceExtractor (name) +{ + // .. nothing yet .. +} + +void NetlistDeviceExtractorDiode::setup () +{ + define_layer ("P", "P region"); // #0 + define_layer ("N", "N region"); // #1 + define_layer ("tA", 0, "A terminal output"); // #2 -> P + define_layer ("tC", 1, "C terminal output"); // #3 -> N + + register_device_class (new db::DeviceClassDiode ()); +} + +db::Connectivity NetlistDeviceExtractorDiode::get_connectivity (const db::Layout & /*layout*/, const std::vector &layers) const +{ + tl_assert (layers.size () >= 2); + + unsigned int pregion = layers [0]; + unsigned int nregion = layers [1]; + + // The layer definition is plate1, plate2 + db::Connectivity conn; + // collect all connected plate 1 shapes + conn.connect (pregion, pregion); + // collect all connected plate 1 shapes + conn.connect (nregion, nregion); + // connect the plates (NOTE that this is a logical, not a physical connection) + conn.connect (pregion, nregion); + return conn; +} + +void NetlistDeviceExtractorDiode::extract_devices (const std::vector &layer_geometry) +{ + size_t pregion_geometry_index = 0; + size_t nregion_geometry_index = 1; + size_t a_terminal_geometry_index = 2; + size_t c_terminal_geometry_index = 3; + + const db::Region &pregion = layer_geometry [pregion_geometry_index]; + const db::Region &nregion = layer_geometry [nregion_geometry_index]; + + db::Region overlap (pregion); + overlap.set_base_verbosity (pregion.base_verbosity ()); + overlap &= nregion; + + for (db::Region::const_iterator p = overlap.begin_merged (); !p.at_end (); ++p) { + + db::Device *device = create_device (); + + device->set_trans (db::DCplxTrans ((p->box ().center () - db::Point ()) * dbu ())); + + double area = p->area () * dbu () * dbu (); + + device->set_parameter_value (db::DeviceClassDiode::param_id_A, area); + device->set_parameter_value (db::DeviceClassDiode::param_id_P, dbu () * p->perimeter ()); + + define_terminal (device, db::DeviceClassDiode::terminal_id_A, a_terminal_geometry_index, *p); + define_terminal (device, db::DeviceClassDiode::terminal_id_C, c_terminal_geometry_index, *p); + + // allow derived classes to modify the device + modify_device (*p, layer_geometry, device); + + // output the device for debugging + device_out (device, db::Region (*p)); + + } +} + } diff --git a/src/db/db/dbNetlistDeviceExtractorClasses.h b/src/db/db/dbNetlistDeviceExtractorClasses.h index 95426e893..05821fb31 100644 --- a/src/db/db/dbNetlistDeviceExtractorClasses.h +++ b/src/db/db/dbNetlistDeviceExtractorClasses.h @@ -108,6 +108,10 @@ private: * The device class produced by this extractor is DeviceClassResistor. * The extractor extracts the three parameters of this class: R, A and P. * A is the area of the wire and P is the perimeter. + * + * The layers are R for the "wire" and "C" for the two contacts and the + * end of the wire. "tA" and "tB" are the layers on which the A and B + * terminals are produced. */ class DB_PUBLIC NetlistDeviceExtractorResistor : public db::NetlistDeviceExtractor @@ -171,7 +175,7 @@ public: * The extractor extracts the three parameters of this class: C, A and P. * A is the area of the overlap area and P is the perimeter. * - * The layers are P1 and P2 for the plates. A and B are layers where + * The layers are P1 and P2 for the plates. tA and tB are layers where * the terminals for A and B are produced respectively. */ class DB_PUBLIC NetlistDeviceExtractorCapacitor @@ -273,6 +277,51 @@ protected: } }; +/** + * @brief A device extractor for a planar diode + * + * This class supplies the generic extractor for a planar diode. + * The diode is defined by two layers whose overlap area forms + * the diode. The p-type layer forms the anode, the n-type layer + * the cathode. + * + * The device class produced by this extractor is DeviceClassDiode. + * The extractor extracts the two parameters of this class: A and P. + * A is the area of the overlap area and P is the perimeter. + * + * The layers are "P" and "N" for the p and n region respectively. + * The terminal output layers are "tA" and "tC" for anode and + * cathode respectively. + */ +class DB_PUBLIC NetlistDeviceExtractorDiode + : public db::NetlistDeviceExtractor +{ +public: + NetlistDeviceExtractorDiode (const std::string &name); + + virtual void setup (); + virtual db::Connectivity get_connectivity (const db::Layout &layout, const std::vector &layers) const; + virtual void extract_devices (const std::vector &layer_geometry); + +protected: + /** + * @brief A callback when the device is produced + * This callback is provided as a debugging port + */ + virtual void device_out (const db::Device * /*device*/, const db::Region & /*diode_area*/) + { + // .. no specific implementation .. + } + + /** + * @brief Allow derived classes to modify the device + */ + virtual void modify_device (const db::Polygon & /*diode_area*/, const std::vector & /*layer_geometry*/, db::Device * /*device*/) + { + // .. no specific implementation .. + } +}; + } namespace tl @@ -320,6 +369,12 @@ template<> struct type_traits : pub typedef tl::false_tag has_default_constructor; }; +template<> struct type_traits : public tl::type_traits +{ + typedef tl::false_tag has_copy_constructor; + typedef tl::false_tag has_default_constructor; +}; + } #endif diff --git a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc index c5769d143..40e759fbc 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc @@ -622,4 +622,34 @@ Class decl_NetlistDeviceExtractorBi "This class has been introduced in version 0.26." ); +db::NetlistDeviceExtractorDiode *make_diode_extractor (const std::string &name) +{ + return new db::NetlistDeviceExtractorDiode (name); +} + +Class decl_NetlistDeviceExtractorDiode (decl_dbNetlistDeviceExtractor, "db", "DeviceExtractorDiode", + gsi::constructor ("new", &make_diode_extractor, gsi::arg ("name"), + "@brief Creates a new device extractor with the given name." + ), + "@brief A device extractor for a planar diode\n" + "\n" + "This class supplies the generic extractor for a planar diode.\n" + "The diode is defined by two layers whose overlap area forms\n" + "the diode. The p-type layer forms the anode, the n-type layer\n" + "the cathode.\n" + "\n" + "The device class produced by this extractor is DeviceClassDiode.\n" + "The extractor extracts the two parameters of this class: A and P.\n" + "A is the area of the overlap area and P is the perimeter.\n" + "\n" + "The layers are \"P\" and \"N\" for the p and n region respectively.\n" + "The terminal output layers are \"tA\" and \"tC\" for anode and \n" + "cathode respectively.\n" + "\n" + "This class is a closed one and methods cannot be reimplemented. To reimplement " + "specific methods, see \\DeviceExtractor.\n" + "\n" + "This class has been introduced in version 0.26." +); + } diff --git a/src/db/unit_tests/dbNetlistDeviceClassesTests.cc b/src/db/unit_tests/dbNetlistDeviceClassesTests.cc index d522698f5..5a97e9c71 100644 --- a/src/db/unit_tests/dbNetlistDeviceClassesTests.cc +++ b/src/db/unit_tests/dbNetlistDeviceClassesTests.cc @@ -840,12 +840,10 @@ TEST(15_SerialDiodes) db::Device *d1 = new db::Device (diode, "d1"); d1->set_parameter_value (db::DeviceClassDiode::param_id_A, 2.0); - d1->set_parameter_value (db::DeviceClassResistor::param_id_A, 5.0); - d1->set_parameter_value (db::DeviceClassResistor::param_id_P, 10.0); + d1->set_parameter_value (db::DeviceClassDiode::param_id_P, 5.0); db::Device *d2 = new db::Device (diode, "d2"); - d2->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 3.0); - d2->set_parameter_value (db::DeviceClassResistor::param_id_A, 1.0); - d2->set_parameter_value (db::DeviceClassResistor::param_id_P, 2.0); + d2->set_parameter_value (db::DeviceClassDiode::param_id_A, 3.0); + d2->set_parameter_value (db::DeviceClassDiode::param_id_P, 1.0); db::Circuit *circuit = new db::Circuit (); nl.add_circuit (circuit); @@ -873,8 +871,8 @@ TEST(15_SerialDiodes) EXPECT_EQ (nl.to_string (), "circuit '' (A=n1,B=n3);\n" - " device '' d1 (A=n1,C=n2) (A=2);\n" - " device '' d2 (A=n2,C=n3) (A=3);\n" + " device '' d1 (A=n1,C=n2) (A=2,P=5);\n" + " device '' d2 (A=n2,C=n3) (A=3,P=1);\n" "end;\n" ); @@ -885,8 +883,8 @@ TEST(15_SerialDiodes) EXPECT_EQ (nl.to_string (), "circuit '' (A=n1,B=n3);\n" - " device '' d1 (A=n1,C=n2) (A=2);\n" - " device '' d2 (A=n2,C=n3) (A=3);\n" + " device '' d1 (A=n1,C=n2) (A=2,P=5);\n" + " device '' d2 (A=n2,C=n3) (A=3,P=1);\n" "end;\n" ); } @@ -900,8 +898,10 @@ TEST(16_ParallelDiodes) db::Device *d1 = new db::Device (diode, "d1"); d1->set_parameter_value (db::DeviceClassDiode::param_id_A, 1.0); + d1->set_parameter_value (db::DeviceClassDiode::param_id_P, 5.0); db::Device *d2 = new db::Device (diode, "d2"); d2->set_parameter_value (db::DeviceClassDiode::param_id_A, 3.0); + d2->set_parameter_value (db::DeviceClassDiode::param_id_P, 2.0); db::Circuit *circuit = new db::Circuit (); nl.add_circuit (circuit); @@ -926,8 +926,8 @@ TEST(16_ParallelDiodes) EXPECT_EQ (nl.to_string (), "circuit '' (A=n1,B=n2);\n" - " device '' d1 (A=n1,C=n2) (A=1);\n" - " device '' d2 (A=n1,C=n2) (A=3);\n" + " device '' d1 (A=n1,C=n2) (A=1,P=5);\n" + " device '' d2 (A=n1,C=n2) (A=3,P=2);\n" "end;\n" ); @@ -936,7 +936,7 @@ TEST(16_ParallelDiodes) EXPECT_EQ (nl.to_string (), "circuit '' (A=n1,B=n2);\n" - " device '' d1 (A=n1,C=n2) (A=4);\n" + " device '' d1 (A=n1,C=n2) (A=4,P=7);\n" "end;\n" ); } @@ -950,8 +950,10 @@ TEST(17_AntiParallelDiodes) db::Device *d1 = new db::Device (diode, "d1"); d1->set_parameter_value (db::DeviceClassDiode::param_id_A, 1.0); + d1->set_parameter_value (db::DeviceClassDiode::param_id_P, 5.0); db::Device *d2 = new db::Device (diode, "d2"); d2->set_parameter_value (db::DeviceClassDiode::param_id_A, 3.0); + d2->set_parameter_value (db::DeviceClassDiode::param_id_P, 2.0); db::Circuit *circuit = new db::Circuit (); nl.add_circuit (circuit); @@ -976,8 +978,8 @@ TEST(17_AntiParallelDiodes) EXPECT_EQ (nl.to_string (), "circuit '' (A=n1,B=n2);\n" - " device '' d1 (A=n1,C=n2) (A=1);\n" - " device '' d2 (A=n2,C=n1) (A=3);\n" + " device '' d1 (A=n1,C=n2) (A=1,P=5);\n" + " device '' d2 (A=n2,C=n1) (A=3,P=2);\n" "end;\n" ); @@ -988,8 +990,8 @@ TEST(17_AntiParallelDiodes) EXPECT_EQ (nl.to_string (), "circuit '' (A=n1,B=n2);\n" - " device '' d1 (A=n1,C=n2) (A=1);\n" - " device '' d2 (A=n2,C=n1) (A=3);\n" + " device '' d1 (A=n1,C=n2) (A=1,P=5);\n" + " device '' d2 (A=n2,C=n1) (A=3,P=2);\n" "end;\n" ); } @@ -1662,3 +1664,402 @@ TEST(34_ParallelMOS4TransistorsDifferentLength) ); } +TEST(35_SerialCapacitorsWithBulk) +{ + db::DeviceClassCapacitorWithBulk *cap = new db::DeviceClassCapacitorWithBulk (); + + db::Netlist nl; + nl.add_device_class (cap); + + db::Device *c1 = new db::Device (cap, "c1"); + c1->set_parameter_value (db::DeviceClassCapacitorWithBulk::param_id_C, 2.0); + c1->set_parameter_value (db::DeviceClassResistor::param_id_A, 5.0); + c1->set_parameter_value (db::DeviceClassResistor::param_id_P, 10.0); + db::Device *c2 = new db::Device (cap, "c2"); + c2->set_parameter_value (db::DeviceClassCapacitorWithBulk::param_id_C, 3.0); + c2->set_parameter_value (db::DeviceClassResistor::param_id_A, 1.0); + c2->set_parameter_value (db::DeviceClassResistor::param_id_P, 2.0); + + db::Circuit *circuit = new db::Circuit (); + nl.add_circuit (circuit); + + db::Pin pin_a = circuit->add_pin ("A"); + db::Pin pin_b = circuit->add_pin ("B"); + db::Pin pin_bulk = circuit->add_pin ("BULK"); + + circuit->add_device (c1); + circuit->add_device (c2); + + db::Net *nb = new db::Net ("nb"); + circuit->add_net (nb); + circuit->connect_pin (pin_bulk.id (), nb); + c1->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_W, nb); + + db::Net *n1 = new db::Net ("n1"); + circuit->add_net (n1); + circuit->connect_pin (pin_a.id (), n1); + c1->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_A, n1); + + db::Net *n2 = new db::Net ("n2"); + circuit->add_net (n2); + c1->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_B, n2); + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_A, n2); + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_W, n2); + + db::Net *n3 = new db::Net ("n3"); + circuit->add_net (n3); + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_B, n3); + circuit->connect_pin (pin_b.id (), n3); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=2,A=5,P=10);\n" + " device '' c2 (A=n2,B=n3,W=n2) (C=3,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + // no combination because bulk terminals are connected differently + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=2,A=5,P=10);\n" + " device '' c2 (A=n2,B=n3,W=n2) (C=3,A=1,P=2);\n" + "end;\n" + ); + + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_W, nb); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=2,A=5,P=10);\n" + " device '' c2 (A=n2,B=n3,W=nb) (C=3,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' c1 (A=n1,B=n3,W=nb) (C=1.2,A=6,P=12);\n" + "end;\n" + ); +} + +TEST(36_ParallelCapacitorsWithBulk) +{ + db::DeviceClassCapacitorWithBulk *cap = new db::DeviceClassCapacitorWithBulk (); + + db::Netlist nl; + nl.add_device_class (cap); + + db::Device *c1 = new db::Device (cap, "c1"); + c1->set_parameter_value (db::DeviceClassCapacitorWithBulk::param_id_C, 1.0); + c1->set_parameter_value (db::DeviceClassResistor::param_id_A, 5.0); + c1->set_parameter_value (db::DeviceClassResistor::param_id_P, 10.0); + db::Device *c2 = new db::Device (cap, "c2"); + c2->set_parameter_value (db::DeviceClassCapacitorWithBulk::param_id_C, 3.0); + c2->set_parameter_value (db::DeviceClassResistor::param_id_A, 1.0); + c2->set_parameter_value (db::DeviceClassResistor::param_id_P, 2.0); + + db::Circuit *circuit = new db::Circuit (); + nl.add_circuit (circuit); + + db::Pin pin_a = circuit->add_pin ("A"); + db::Pin pin_b = circuit->add_pin ("B"); + db::Pin pin_bulk = circuit->add_pin ("BULK"); + + circuit->add_device (c1); + circuit->add_device (c2); + + db::Net *nb = new db::Net ("nb"); + circuit->add_net (nb); + circuit->connect_pin (pin_bulk.id (), nb); + c1->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_W, nb); + + db::Net *n1 = new db::Net ("n1"); + circuit->add_net (n1); + circuit->connect_pin (pin_a.id (), n1); + c1->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_A, n1); + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_A, n1); + + db::Net *n2 = new db::Net ("n2"); + circuit->add_net (n2); + circuit->connect_pin (pin_b.id (), n2); + c1->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_B, n2); + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_B, n2); + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_W, n2); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=1,A=5,P=10);\n" + " device '' c2 (A=n1,B=n2,W=n2) (C=3,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + // devices are not combined as the bulk terminals are connected differently + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=1,A=5,P=10);\n" + " device '' c2 (A=n1,B=n2,W=n2) (C=3,A=1,P=2);\n" + "end;\n" + ); + + c2->connect_terminal (db::DeviceClassCapacitorWithBulk::terminal_id_W, nb); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=1,A=5,P=10);\n" + " device '' c2 (A=n1,B=n2,W=nb) (C=3,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' c1 (A=n1,B=n2,W=nb) (C=4,A=6,P=12);\n" + "end;\n" + ); +} + +TEST(37_SerialResistorsWithBulk) +{ + db::DeviceClassResistorWithBulk *cap = new db::DeviceClassResistorWithBulk (); + + db::Netlist nl; + nl.add_device_class (cap); + + db::Device *r1 = new db::Device (cap, "r1"); + r1->set_parameter_value (db::DeviceClassResistorWithBulk::param_id_R, 2.0); + r1->set_parameter_value (db::DeviceClassResistor::param_id_A, 5.0); + r1->set_parameter_value (db::DeviceClassResistor::param_id_P, 10.0); + db::Device *r2 = new db::Device (cap, "r2"); + r2->set_parameter_value (db::DeviceClassResistorWithBulk::param_id_R, 0.5); + r2->set_parameter_value (db::DeviceClassResistor::param_id_A, 1.0); + r2->set_parameter_value (db::DeviceClassResistor::param_id_P, 2.0); + + db::Circuit *circuit = new db::Circuit (); + nl.add_circuit (circuit); + + db::Pin pin_a = circuit->add_pin ("A"); + db::Pin pin_b = circuit->add_pin ("B"); + db::Pin pin_bulk = circuit->add_pin ("BULK"); + + circuit->add_device (r1); + circuit->add_device (r2); + + db::Net *nb = new db::Net ("nb"); + circuit->add_net (nb); + circuit->connect_pin (pin_bulk.id (), nb); + r1->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_W, nb); + + db::Net *n1 = new db::Net ("n1"); + circuit->add_net (n1); + circuit->connect_pin (pin_a.id (), n1); + r1->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_A, n1); + + db::Net *n2 = new db::Net ("n2"); + circuit->add_net (n2); + r1->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_B, n2); + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_A, n2); + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_W, n2); + + db::Net *n3 = new db::Net ("n3"); + circuit->add_net (n3); + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_B, n3); + circuit->connect_pin (pin_b.id (), n3); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=2,A=5,P=10);\n" + " device '' r2 (A=n2,B=n3,W=n2) (R=0.5,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + // no combination because bulk terminals are connected differently + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=2,A=5,P=10);\n" + " device '' r2 (A=n2,B=n3,W=n2) (R=0.5,A=1,P=2);\n" + "end;\n" + ); + + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_W, nb); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=2,A=5,P=10);\n" + " device '' r2 (A=n2,B=n3,W=nb) (R=0.5,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n3,BULK=nb);\n" + " device '' r1 (A=n1,B=n3,W=nb) (R=2.5,A=6,P=12);\n" + "end;\n" + ); +} + +TEST(38_ParallelResistorsWithBulk) +{ + db::DeviceClassResistorWithBulk *cap = new db::DeviceClassResistorWithBulk (); + + db::Netlist nl; + nl.add_device_class (cap); + + db::Device *r1 = new db::Device (cap, "r1"); + r1->set_parameter_value (db::DeviceClassResistorWithBulk::param_id_R, 2.0); + r1->set_parameter_value (db::DeviceClassResistor::param_id_A, 5.0); + r1->set_parameter_value (db::DeviceClassResistor::param_id_P, 10.0); + db::Device *r2 = new db::Device (cap, "r2"); + r2->set_parameter_value (db::DeviceClassResistorWithBulk::param_id_R, 0.5); + r2->set_parameter_value (db::DeviceClassResistor::param_id_A, 1.0); + r2->set_parameter_value (db::DeviceClassResistor::param_id_P, 2.0); + + db::Circuit *circuit = new db::Circuit (); + nl.add_circuit (circuit); + + db::Pin pin_a = circuit->add_pin ("A"); + db::Pin pin_b = circuit->add_pin ("B"); + db::Pin pin_bulk = circuit->add_pin ("BULK"); + + circuit->add_device (r1); + circuit->add_device (r2); + + db::Net *nb = new db::Net ("nb"); + circuit->add_net (nb); + circuit->connect_pin (pin_bulk.id (), nb); + r1->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_W, nb); + + db::Net *n1 = new db::Net ("n1"); + circuit->add_net (n1); + circuit->connect_pin (pin_a.id (), n1); + r1->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_A, n1); + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_A, n1); + + db::Net *n2 = new db::Net ("n2"); + circuit->add_net (n2); + circuit->connect_pin (pin_b.id (), n2); + r1->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_B, n2); + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_B, n2); + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_W, n2); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=2,A=5,P=10);\n" + " device '' r2 (A=n1,B=n2,W=n2) (R=0.5,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + // devices are not combined as the bulk terminals are connected differently + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=2,A=5,P=10);\n" + " device '' r2 (A=n1,B=n2,W=n2) (R=0.5,A=1,P=2);\n" + "end;\n" + ); + + r2->connect_terminal (db::DeviceClassResistorWithBulk::terminal_id_W, nb); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=2,A=5,P=10);\n" + " device '' r2 (A=n1,B=n2,W=nb) (R=0.5,A=1,P=2);\n" + "end;\n" + ); + + nl.combine_devices (); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,BULK=nb);\n" + " device '' r1 (A=n1,B=n2,W=nb) (R=0.4,A=6,P=12);\n" + "end;\n" + ); +} + +TEST(39_ParallelBipolarTransistors) +{ + db::DeviceClassBipolarTransistor *cls = new db::DeviceClassBipolarTransistor (); + + db::Netlist nl; + nl.add_device_class (cls); + + db::Device *d1 = new db::Device (cls, "d1"); + d1->set_parameter_value (db::DeviceClassBipolarTransistor::param_id_AE, 2.0); + d1->set_parameter_value (db::DeviceClassBipolarTransistor::param_id_PE, 12.0); + db::Device *d2 = new db::Device (cls, "d2"); + d2->set_parameter_value (db::DeviceClassBipolarTransistor::param_id_AE, 3.0); + d2->set_parameter_value (db::DeviceClassBipolarTransistor::param_id_PE, 13.0); + + db::Circuit *circuit = new db::Circuit (); + nl.add_circuit (circuit); + + db::Pin pin_a = circuit->add_pin ("A"); + db::Pin pin_b = circuit->add_pin ("B"); + db::Pin pin_c = circuit->add_pin ("C"); + + circuit->add_device (d1); + circuit->add_device (d2); + + db::Net *n1 = new db::Net ("n1"); + circuit->add_net (n1); + circuit->connect_pin (pin_a.id (), n1); + d1->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_C, n1); + d2->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_C, n1); + + db::Net *n2 = new db::Net ("n2"); + circuit->add_net (n2); + circuit->connect_pin (pin_b.id (), n2); + d1->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_B, n2); + d2->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_B, n2); + d2->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_E, n2); + + db::Net *n3 = new db::Net ("n3"); + circuit->add_net (n3); + circuit->connect_pin (pin_c.id (), n3); + d1->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_E, n3); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,C=n3);\n" + " device '' d1 (C=n1,B=n2,E=n3) (AE=2,PE=12);\n" + " device '' d2 (C=n1,B=n2,E=n2) (AE=3,PE=13);\n" + "end;\n" + ); + + nl.combine_devices (); + + // no combination as emitters are connected differently + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,C=n3);\n" + " device '' d1 (C=n1,B=n2,E=n3) (AE=2,PE=12);\n" + " device '' d2 (C=n1,B=n2,E=n2) (AE=3,PE=13);\n" + "end;\n" + ); + + d2->connect_terminal (db::DeviceClassBipolarTransistor::terminal_id_E, n3); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,C=n3);\n" + " device '' d1 (C=n1,B=n2,E=n3) (AE=2,PE=12);\n" + " device '' d2 (C=n1,B=n2,E=n3) (AE=3,PE=13);\n" + "end;\n" + ); + + nl.combine_devices (); + + EXPECT_EQ (nl.to_string (), + "circuit '' (A=n1,B=n2,C=n3);\n" + " device '' d1 (C=n1,B=n2,E=n3) (AE=5,PE=25);\n" + "end;\n" + ); +} + diff --git a/src/laybasic/laybasic/images/icon_device_bjt_16.png b/src/laybasic/laybasic/images/icon_device_bjt_16.png new file mode 100644 index 000000000..c6855dc75 Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_bjt_16.png differ diff --git a/src/laybasic/laybasic/images/icon_device_bjt_24.png b/src/laybasic/laybasic/images/icon_device_bjt_24.png new file mode 100644 index 000000000..b4521fb5c Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_bjt_24.png differ diff --git a/src/laybasic/laybasic/images/icon_device_bjt_32.png b/src/laybasic/laybasic/images/icon_device_bjt_32.png new file mode 100644 index 000000000..c1250e00a Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_bjt_32.png differ diff --git a/src/laybasic/laybasic/images/icon_device_bjt_48.png b/src/laybasic/laybasic/images/icon_device_bjt_48.png new file mode 100644 index 000000000..c07b88290 Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_bjt_48.png differ diff --git a/src/laybasic/laybasic/images/icon_device_diode_16.png b/src/laybasic/laybasic/images/icon_device_diode_16.png new file mode 100644 index 000000000..39af006f3 Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_diode_16.png differ diff --git a/src/laybasic/laybasic/images/icon_device_diode_24.png b/src/laybasic/laybasic/images/icon_device_diode_24.png new file mode 100644 index 000000000..6b17f4b3a Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_diode_24.png differ diff --git a/src/laybasic/laybasic/images/icon_device_diode_32.png b/src/laybasic/laybasic/images/icon_device_diode_32.png new file mode 100644 index 000000000..81309c8a5 Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_diode_32.png differ diff --git a/src/laybasic/laybasic/images/icon_device_diode_48.png b/src/laybasic/laybasic/images/icon_device_diode_48.png new file mode 100644 index 000000000..a1f1fc550 Binary files /dev/null and b/src/laybasic/laybasic/images/icon_device_diode_48.png differ diff --git a/src/laybasic/laybasic/images/icons.svg b/src/laybasic/laybasic/images/icons.svg index 8dee44d0c..877631746 100644 --- a/src/laybasic/laybasic/images/icons.svg +++ b/src/laybasic/laybasic/images/icons.svg @@ -25,9 +25,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.4142136" - inkscape:cx="346.93569" - inkscape:cy="970.66949" + inkscape:zoom="1" + inkscape:cx="-37.273909" + inkscape:cy="695.91553" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -39,7 +39,9 @@ inkscape:window-height="991" inkscape:window-x="34" inkscape:window-y="51" - inkscape:window-maximized="0"> + inkscape:window-maximized="0" + inkscape:snap-global="true" + inkscape:snap-others="false"> + + icon_device_bjt_48.png + + + + + + + + + + + + + + + icon_device_bjt_32.png + icon_device_bjt_24.png + icon_device_bjt_16.png + + + + + + + + + + + + + + + + + + + icon_device_diode_48.png + + + + + + + + + icon_device_diode_32.png + icon_device_diode_24.png + icon_device_diode_16.png + + + + + + + + + + + diff --git a/src/laybasic/laybasic/layNetlistBrowserModel.cc b/src/laybasic/laybasic/layNetlistBrowserModel.cc index b9e1e2639..acf94560f 100644 --- a/src/laybasic/laybasic/layNetlistBrowserModel.cc +++ b/src/laybasic/laybasic/layNetlistBrowserModel.cc @@ -1510,17 +1510,33 @@ static QIcon icon_for_pin () static QIcon icon_for_device (const db::DeviceClass *dc) { QIcon icon; - // TODO: diode, inductor, generic device ... + // TODO: inductor, generic device ... if (dynamic_cast (dc)) { icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_48.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_32.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_24.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_16.png"))); + } else if (dynamic_cast (dc)) { + // fake ... + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_res_16.png"))); } else if (dynamic_cast (dc)) { icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_48.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_32.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_24.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_cap_16.png"))); + } else if (dynamic_cast (dc)) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_diode_16.png"))); + } else if (dynamic_cast (dc)) { + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_48.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_32.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_24.png"))); + icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_bjt_16.png"))); } else { icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_mos_48.png"))); icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_device_mos_32.png"))); diff --git a/src/laybasic/laybasic/laybasicResources.qrc b/src/laybasic/laybasic/laybasicResources.qrc index 39169648c..a5ff51cce 100644 --- a/src/laybasic/laybasic/laybasicResources.qrc +++ b/src/laybasic/laybasic/laybasicResources.qrc @@ -36,5 +36,13 @@ images/icon_conn_light_24.png images/icon_conn_light_32.png images/icon_conn_light_48.png + images/icon_device_diode_16.png + images/icon_device_diode_24.png + images/icon_device_diode_32.png + images/icon_device_diode_48.png + images/icon_device_bjt_48.png + images/icon_device_bjt_32.png + images/icon_device_bjt_24.png + images/icon_device_bjt_16.png