From aa5e8852158c1134cf9822d7a91dbf4466e1a44c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 24 Dec 2018 00:08:34 +0100 Subject: [PATCH] Added Ruby tests for GSI binding of db::Netlist classes --- src/db/db/dbNetlist.cc | 14 +- src/db/db/dbNetlist.h | 8 +- src/db/db/gsiDeclDbNetlist.cc | 82 +++--- src/db/unit_tests/dbNetlistTests.cc | 48 ++-- testdata/ruby/dbNetlist.rb | 372 +++++++++++++++++++++++++++- 5 files changed, 443 insertions(+), 81 deletions(-) diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index bbe1dc381..92612bf48 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -289,15 +289,16 @@ NetPinRef &NetPinRef::operator= (const NetPinRef &other) return *this; } -const Pin *NetPinRef::pin (const db::Circuit *c) const +const Pin *NetPinRef::pin () const { if (! mp_subcircuit) { - tl_assert (c != 0); - return c->pin_by_id (m_pin_id); - } else { - tl_assert (mp_subcircuit->circuit () != 0); + if (mp_net && mp_net->circuit ()) { + return mp_net->circuit ()->pin_by_id (m_pin_id); + } + } else if (mp_subcircuit->circuit ()) { return mp_subcircuit->circuit ()->pin_by_id (m_pin_id); } + return 0; } // -------------------------------------------------------------------------------- @@ -645,10 +646,11 @@ const std::string &DeviceClass::description () const return no_description; } -void DeviceClass::add_port_definition (const DevicePortDefinition &pd) +const DevicePortDefinition &DeviceClass::add_port_definition (const DevicePortDefinition &pd) { m_port_definitions.push_back (pd); m_port_definitions.back ().set_id (m_port_definitions.size () - 1); + return m_port_definitions.back (); } void DeviceClass::clear_port_definitions () diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index b22887454..432ec77a2 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -188,11 +188,9 @@ public: /** * @brief Gets the pin reference from the pin id - * - * The circuit is the one where the net is defined. It is used to - * resolve outgoing pints. + * If the pin cannot be resolved, null is returned. */ - const Pin *pin (const Circuit *c) const; + const Pin *pin () const; /** * @brief Gets the subcircuit reference @@ -1177,7 +1175,7 @@ public: /** * @brief Adds a port definition */ - void add_port_definition (const DevicePortDefinition &pd); + const DevicePortDefinition &add_port_definition (const DevicePortDefinition &pd); /** * @brief Clears the port definition diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index bb3cbba09..37e77fd57 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -35,7 +35,9 @@ Class decl_dbPin ("db", "Pin", ), "@brief A pin of a circuit.\n" "Pin objects are used to describe the outgoing pins of " - "a circuit. To create a new pin of a circuit, use \\Circuit#create_pin." + "a circuit. To create a new pin of a circuit, use \\Circuit#create_pin.\n" + "\n" + "This class has been added in version 0.26." ); static void device_disconnect_port (db::Device *device, size_t port_id) @@ -76,7 +78,9 @@ Class decl_dbDevice ("db", "Device", "obtained from the device class using the \\DeviceClass#port_definitions method.\n" "\n" "Devices connect to nets through the \\Device#connect_port method. " - "Device ports can be disconnected using \\Device#disconnect_port." + "Device ports can be disconnected using \\Device#disconnect_port.\n" + "\n" + "This class has been added in version 0.26." ); static void subcircuit_connect_pin1 (db::SubCircuit *subcircuit, const db::Pin *pin, db::Net *net) @@ -136,7 +140,9 @@ Class decl_dbSubCircuit ("db", "SubCircuit", "are identical to the outgoing pins of the circuit the subcircuit refers to.\n" "\n" "Subcircuits connect to nets through the \\SubCircuit#connect_pin method. " - "SubCircuit pins can be disconnected using \\SubCircuit#disconnect_pin." + "SubCircuit pins can be disconnected using \\SubCircuit#disconnect_pin.\n" + "\n" + "This class has been added in version 0.26." ); Class decl_dbNetPortRef ("db", "NetPortRef", @@ -157,7 +163,9 @@ Class decl_dbNetPortRef ("db", "NetPortRef", "@brief Gets the port definition of the port that is connected" ), "@brief A connection to a port of a device.\n" - "This object is used inside a net (see \\Net) to describe the connections a net makes." + "This object is used inside a net (see \\Net) to describe the connections a net makes.\n" + "\n" + "This class has been added in version 0.26." ); Class decl_dbNetPinRef ("db", "NetPinRef", @@ -179,7 +187,9 @@ Class decl_dbNetPinRef ("db", "NetPinRef", "@brief Gets the net this pin reference is attached to" ), "@brief A connection to a pin of a subcircuit or an outgoing pin of the circuit.\n" - "This object is used inside a net (see \\Net) to describe the connections a net makes." + "This object is used inside a net (see \\Net) to describe the connections a net makes.\n" + "\n" + "This class has been added in version 0.26." ); Class decl_dbNet ("db", "Net", @@ -228,7 +238,9 @@ Class decl_dbNet ("db", "Net", "To connect a net to a pin of a subcircuit, use \\SubCircuit#connect_pin, to " "disconnect a net from a pin of a subcircuit, use \\SubCircuit#disconnect_pin. " "To connect a net to a port of a device, use \\Device#connect_port, to " - "disconnect a net from a port of a device, use \\Device#disconnect_port. " + "disconnect a net from a port of a device, use \\Device#disconnect_port.\n" + "\n" + "This class has been added in version 0.26." ); Class decl_dbDevicePortDefinition ("db", "DevicePortDefinition", @@ -250,7 +262,9 @@ Class decl_dbDevicePortDefinition ("db", "DevicePortDe "the \\NetPortRef object)." ), "@brief A port descriptor\n" - "This class is used inside the \\DeviceClass class to describe a port of the device." + "This class is used inside the \\DeviceClass class to describe a port of the device.\n" + "\n" + "This class has been added in version 0.26." ); Class decl_dbDeviceClass ("db", "DeviceClass", @@ -270,15 +284,29 @@ Class decl_dbDeviceClass ("db", "DeviceClass", "This method obtains the corresponding definition object." ), "@brief A class describing a specific type of device.\n" - "This is the base class for the device class.\n" + "Device class objects live in the context of a \\Netlist object. After a " + "device class is created, it must be added to the netlist using \\Netlist#add. " + "The netlist will own the device class object. When the netlist is destroyed, the " + "device class object will become invalid.\n" + "\n" + "The \\DeviceClass class is the base class for other device classes.\n" "\n" "This class has been added in version 0.26." ); +static void gdc_add_port_definition (db::GenericDeviceClass *cls, db::DevicePortDefinition *port_def) +{ + if (port_def) { + *port_def = cls->add_port_definition (*port_def); + } +} + Class decl_dbGenericDeviceClass (decl_dbDeviceClass, "db", "GenericDeviceClass", - gsi::method ("add_port", &db::GenericDeviceClass::add_port_definition, gsi::arg ("port_def"), + gsi::method_ext ("add_port", &gsi::gdc_add_port_definition, gsi::arg ("port_def"), "@brief Adds the given port definition to the device class\n" - "This method will define a new port. The new port is added at the end of existing ports." + "This method will define a new port. The new port is added at the end of existing ports. " + "The port definition object passed as the argument is modified to contain the " + "new ID of the port." ) + gsi::method ("clear_ports", &db::GenericDeviceClass::clear_port_definitions, "@brief Clears the list of ports\n" @@ -294,7 +322,7 @@ Class decl_dbGenericDeviceClass (decl_dbDeviceClass, "db "by adding port definitions. Port definitions should not be added dynamically. To create " "your own device, instantiate the \\GenericDeviceClass object, set name and description and " "specify the ports. Then add this new device class to the \\Netlist object where it will live " - "and be used to define device instances (\\Device objects)." + "and be used to define device instances (\\Device objects).\n" "\n" "This class has been added in version 0.26." ); @@ -311,13 +339,6 @@ static db::Net *create_net (db::Circuit *c) return n; } -static db::Device *create_device (db::Circuit *c) -{ - db::Device *d = new db::Device (); - c->add_device (d); - return d; -} - static db::Device *create_device1 (db::Circuit *c, db::DeviceClass *dc, const std::string &name) { db::Device *d = new db::Device (dc, name); @@ -325,13 +346,6 @@ static db::Device *create_device1 (db::Circuit *c, db::DeviceClass *dc, const st return d; } -static db::SubCircuit *create_subcircuit (db::Circuit *c) -{ - db::SubCircuit *sc = new db::SubCircuit (); - c->add_sub_circuit (sc); - return sc; -} - static db::SubCircuit *create_subcircuit1 (db::Circuit *c, db::Circuit *cc, const std::string &name) { db::SubCircuit *sc = new db::SubCircuit (cc, name); @@ -395,13 +409,6 @@ Class decl_dbCircuit ("db", "Circuit", gsi::iterator ("each_net", (db::Circuit::net_iterator (db::Circuit::*) ()) &db::Circuit::begin_nets, (db::Circuit::net_iterator (db::Circuit::*) ()) &db::Circuit::end_nets, "@brief Iterates over the nets of the circuit" ) + - gsi::method_ext ("create_device", &gsi::create_device, - "@brief Creates a new unbound \\Device object inside the circuit\n" - "This object describes a device of the circuit. Unbound devices need to be attached " - "to a device class before they can be used.\n" - "\n" - "For more details see the \\Device class." - ) + gsi::method_ext ("create_device", &gsi::create_device1, gsi::arg ("device_class"), gsi::arg ("name", std::string ()), "@brief Creates a new bound \\Device object inside the circuit\n" "This object describes a device of the circuit. The device is already attached " @@ -416,13 +423,6 @@ Class decl_dbCircuit ("db", "Circuit", gsi::iterator ("each_device", (db::Circuit::device_iterator (db::Circuit::*) ()) &db::Circuit::begin_devices, (db::Circuit::device_iterator (db::Circuit::*) ()) &db::Circuit::end_devices, "@brief Iterates over the devices of the circuit" ) + - gsi::method_ext ("create_subcircuit", &gsi::create_subcircuit, - "@brief Creates a new unbound \\SubCircuit object inside the circuit\n" - "This object describes an instance of another circuit (sub-circuit). Unbound sub-circuits need " - "to be attached to a circuit before they can be used.\n" - "\n" - "For more details see the \\SubCircuit class." - ) + gsi::method_ext ("create_subcircuit", &gsi::create_subcircuit1, gsi::arg ("circuit"), gsi::arg ("name", std::string ()), "@brief Creates a new bound \\SubCircuit object inside the circuit\n" "This object describes an instance of another circuit inside the circuit. The subcircuit is already attached " @@ -506,8 +506,8 @@ Class decl_dbCircuit ("db", "Circuit", "See there for more about nets.\n" "\n" "The Circuit object is only valid if the netlist object is alive. " - "After the netlist object has been destroyed, the Circuit objects " - "must not be accessed anymore. Doing so, may result in a crash.\n" + "Circuits must be added to a netlist using \\Netlist#add to become " + "part of the netlist.\n" "\n" "The Circuit class has been introduced in version 0.26." ); diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 1a58b856e..c6e5e7b43 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -128,7 +128,7 @@ TEST(3_CircuitBasic) EXPECT_EQ (c2.pin_by_id (2), 0); } -static std::string net2string (const db::Net &n, const db::Circuit *c = 0) +static std::string net2string (const db::Net &n) { std::string res; for (db::Net::const_port_iterator i = n.begin_ports (); i != n.end_ports (); ++i) { @@ -149,7 +149,7 @@ static std::string net2string (const db::Net &n, const db::Circuit *c = 0) } else { res += "+"; } - res += i->pin (c) ? i->pin (c)->name () : "(null)"; + res += i->pin () ? i->pin ()->name () : "(null)"; } return res; } @@ -158,7 +158,7 @@ static std::string nets2string (const db::Circuit &c) { std::string res; for (db::Circuit::const_net_iterator n = c.begin_nets (); n != c.end_nets (); ++n) { - res += net2string (*n, &c); + res += net2string (*n); res += "\n"; } return res; @@ -526,8 +526,8 @@ TEST(7_NetPortsEditing) EXPECT_EQ (d2->net_for_port (0), n2); EXPECT_EQ (d2->net_for_port (1), n1); - EXPECT_EQ (net2string (*n1, &c), "D1:A,D2:B"); - EXPECT_EQ (net2string (*n2, &c), "D1:B,D2:A"); + EXPECT_EQ (net2string (*n1), "D1:A,D2:B"); + EXPECT_EQ (net2string (*n2), "D1:B,D2:A"); d1->connect_port (0, n2); d1->connect_port (1, n1); @@ -535,14 +535,14 @@ TEST(7_NetPortsEditing) EXPECT_EQ (d1->net_for_port (0), n2); EXPECT_EQ (d1->net_for_port (1), n1); - EXPECT_EQ (net2string (*n1, &c), "D2:B,D1:B"); - EXPECT_EQ (net2string (*n2, &c), "D2:A,D1:A"); + EXPECT_EQ (net2string (*n1), "D2:B,D1:B"); + EXPECT_EQ (net2string (*n2), "D2:A,D1:A"); d1->connect_port (0, 0); EXPECT_EQ (d1->net_for_port (0), 0); - EXPECT_EQ (net2string (*n1, &c), "D2:B,D1:B"); - EXPECT_EQ (net2string (*n2, &c), "D2:A"); + EXPECT_EQ (net2string (*n1), "D2:B,D1:B"); + EXPECT_EQ (net2string (*n2), "D2:A"); delete d1; d1 = 0; @@ -550,8 +550,8 @@ TEST(7_NetPortsEditing) EXPECT_EQ (c.begin_devices ()->name (), "D2"); EXPECT_EQ (++c.begin_devices () == c.end_devices (), true); - EXPECT_EQ (net2string (*n1, &c), "D2:B"); - EXPECT_EQ (net2string (*n2, &c), "D2:A"); + EXPECT_EQ (net2string (*n1), "D2:B"); + EXPECT_EQ (net2string (*n2), "D2:A"); delete n1; n1 = 0; @@ -559,7 +559,7 @@ TEST(7_NetPortsEditing) EXPECT_EQ (c.begin_nets ()->name (), "n2"); EXPECT_EQ (++c.begin_nets () == c.end_nets (), true); - EXPECT_EQ (net2string (*n2, &c), "D2:A"); + EXPECT_EQ (net2string (*n2), "D2:A"); EXPECT_EQ (d2->net_for_port (0), n2); EXPECT_EQ (d2->net_for_port (1), 0); @@ -611,14 +611,14 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (sc2->net_for_pin (0), n2); EXPECT_EQ (sc2->net_for_pin (1), n1); - EXPECT_EQ (net2string (*n1, &c), "+X,sc1:A,sc2:B"); - EXPECT_EQ (net2string (*n2, &c), "sc1:B,sc2:A"); + EXPECT_EQ (net2string (*n1), "+X,sc1:A,sc2:B"); + EXPECT_EQ (net2string (*n2), "sc1:B,sc2:A"); c.connect_pin (0, 0); EXPECT_EQ (c.net_for_pin (0), 0); - EXPECT_EQ (net2string (*n1, &c), "sc1:A,sc2:B"); - EXPECT_EQ (net2string (*n2, &c), "sc1:B,sc2:A"); + EXPECT_EQ (net2string (*n1), "sc1:A,sc2:B"); + EXPECT_EQ (net2string (*n2), "sc1:B,sc2:A"); sc1->connect_pin (0, n2); sc1->connect_pin (1, n1); @@ -626,14 +626,14 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (sc1->net_for_pin (0), n2); EXPECT_EQ (sc1->net_for_pin (1), n1); - EXPECT_EQ (net2string (*n1, &c), "sc2:B,sc1:B"); - EXPECT_EQ (net2string (*n2, &c), "sc2:A,sc1:A"); + EXPECT_EQ (net2string (*n1), "sc2:B,sc1:B"); + EXPECT_EQ (net2string (*n2), "sc2:A,sc1:A"); sc1->connect_pin (0, 0); EXPECT_EQ (sc1->net_for_pin (0), 0); - EXPECT_EQ (net2string (*n1, &c), "sc2:B,sc1:B"); - EXPECT_EQ (net2string (*n2, &c), "sc2:A"); + EXPECT_EQ (net2string (*n1), "sc2:B,sc1:B"); + EXPECT_EQ (net2string (*n2), "sc2:A"); delete sc1; sc1 = 0; @@ -641,11 +641,11 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (c.begin_sub_circuits ()->name (), "sc2"); EXPECT_EQ (++c.begin_sub_circuits () == c.end_sub_circuits (), true); - EXPECT_EQ (net2string (*n1, &c), "sc2:B"); - EXPECT_EQ (net2string (*n2, &c), "sc2:A"); + EXPECT_EQ (net2string (*n1), "sc2:B"); + EXPECT_EQ (net2string (*n2), "sc2:A"); c.connect_pin (1, n1); - EXPECT_EQ (net2string (*n1, &c), "sc2:B,+Y"); + EXPECT_EQ (net2string (*n1), "sc2:B,+Y"); EXPECT_EQ (c.net_for_pin (1), n1); delete n1; @@ -656,7 +656,7 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (c.begin_nets ()->name (), "n2"); EXPECT_EQ (++c.begin_nets () == c.end_nets (), true); - EXPECT_EQ (net2string (*n2, &c), "sc2:A"); + EXPECT_EQ (net2string (*n2), "sc2:A"); EXPECT_EQ (sc2->net_for_pin (0), n2); EXPECT_EQ (sc2->net_for_pin (1), 0); diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index eab0292cc..5ab05a419 100644 --- a/testdata/ruby/dbNetlist.rb +++ b/testdata/ruby/dbNetlist.rb @@ -25,10 +25,11 @@ load("test_prologue.rb") class DBNetlist_TestClass < TestBase - def test_1_Basic + def test_1_NetlistBasicCircuit nl = RBA::Netlist::new - c = nl.create_circuit + c = RBA::Circuit::new + nl.add(c) c.name = "XYZ" assert_equal(c.name, "XYZ") @@ -36,7 +37,8 @@ class DBNetlist_TestClass < TestBase c.cell_index = 42 assert_equal(c.cell_index, 42) - cc = nl.create_circuit + cc = RBA::Circuit::new + nl.add(cc) cc.name = "ABC" names = [] @@ -50,7 +52,8 @@ class DBNetlist_TestClass < TestBase nl.each_circuit { |i| names << i.name } assert_equal(names, [ c.name ]) - cc = nl.create_circuit + cc = RBA::Circuit::new + nl.add(cc) cc.name = "UVW" names = [] @@ -58,14 +61,373 @@ class DBNetlist_TestClass < TestBase assert_equal(names, [ c.name, cc.name ]) # same as _destroy - nl.remove_circuit(c) + nl.remove(c) names = [] nl.each_circuit { |i| names << i.name } assert_equal(names, [ cc.name ]) + nl._destroy + assert_equal(cc._destroyed?, true) + + end + + def test_2_NetlistBasicDeviceClass + + nl = RBA::Netlist::new + c = RBA::GenericDeviceClass::new + nl.add(c) + + c.name = "XYZ" + assert_equal(c.name, "XYZ") + + cc = RBA::GenericDeviceClass::new + nl.add(cc) + cc.name = "ABC" + + names = [] + nl.each_device_class { |i| names << i.name } + assert_equal(names, [ c.name, cc.name ]) + + # NOTE: this will also remove the circuit from the netlist + cc._destroy + + names = [] + nl.each_device_class { |i| names << i.name } + assert_equal(names, [ c.name ]) + + cc = RBA::GenericDeviceClass::new + nl.add(cc) + cc.name = "UVW" + + names = [] + nl.each_device_class { |i| names << i.name } + assert_equal(names, [ c.name, cc.name ]) + + # same as _destroy + nl.remove(c) + + names = [] + nl.each_device_class { |i| names << i.name } + assert_equal(names, [ cc.name ]) + + nl._destroy + assert_equal(cc._destroyed?, true) + + end + + def test_3_Pin + + c = RBA::Circuit::new + p1 = c.create_pin("A") + p2 = c.create_pin("B") + + assert_equal(p1.id, 0) + assert_equal(p2.id, 1) + + names = [] + c.each_pin { |p| names << p.name } + assert_equal(names, [ "A", "B" ]) + + end + + def test_4_Device + + nl = RBA::Netlist::new + + dc = RBA::GenericDeviceClass::new + nl.add(dc) + dc.name = "DC" + dc.description = "A device class" + + pd = RBA::DevicePortDefinition::new + pd.name = "A" + pd.description = "Port A" + dc.add_port(pd) + + pd = RBA::DevicePortDefinition::new + pd.name = "B" + pd.description = "Port B" + dc.add_port(pd) + + c = RBA::Circuit::new + nl.add(c) + + d1 = c.create_device(dc) + d1.name = "D1" + assert_equal(d1.name, "D1") + + d2 = c.create_device(dc) + d2.name = "D2" + + names = [] + dcs = [] + c.each_device { |d| names << d.name; dcs << d.device_class.name } + assert_equal(names, [ "D1", "D2" ]) + assert_equal(dcs, [ "DC", "DC" ]) + + c.remove_device(d2) + + names = [] + c.each_device { |d| names << d.name } + assert_equal(names, [ "D1" ]) + + d2 = c.create_device(dc, "D2") + + names = [] + dcs = [] + c.each_device { |d| names << d.name; dcs << d.device_class.name } + assert_equal(names, [ "D1", "D2" ]) + assert_equal(dcs, [ "DC", "DC" ]) + + net = c.create_net + net.name = "NET" + + d1.connect_port(1, net) + assert_equal(d1.net_for_port(1).name, "NET") + assert_equal(d1.net_for_port(0).inspect, "nil") + + d2.connect_port(0, net) + + dnames = [] + net.each_port { |p| dnames << p.device.name + ":" + p.port_def.name } + assert_equal(dnames, [ "D1:B", "D2:A" ]) + dnames = [] + net.each_port { |p| dnames << p.device_class.name + ":" + p.port_id.to_s } + assert_equal(dnames, [ "DC:1", "DC:0" ]) + net.each_port { |p| assert_equal(p.net.name, "NET") } + + d1.disconnect_port(1) + assert_equal(d1.net_for_port(1).inspect, "nil") + + dnames = [] + net.each_port { |p| dnames << p.device.name + ":" + p.port_def.name } + assert_equal(dnames, [ "D2:A" ]) + net.each_port { |p| assert_equal(p.net.name, "NET") } + + net.clear + assert_equal(d1.net_for_port(1).inspect, "nil") + assert_equal(d1.net_for_port(0).inspect, "nil") + + end + + def test_5_SubCircuit + + nl = RBA::Netlist::new + + cc = RBA::Circuit::new + cc.name = "CC" + nl.add(cc) + + p1 = cc.create_pin("A") + p2 = cc.create_pin("B") + + assert_equal(p1.id, 0) + assert_equal(p2.id, 1) + + c = RBA::Circuit::new + c.name = "C" + nl.add(c) + + sc1 = c.create_subcircuit(cc) + sc1.name = "SC1" + assert_equal(sc1.name, "SC1") + assert_equal(sc1.circuit.name, "CC") + + sc2 = c.create_subcircuit(cc) + sc2.name = "SC2" + + names = [] + ccn = [] + c.each_subcircuit { |sc| names << sc.name; ccn << sc.circuit.name } + assert_equal(names, [ "SC1", "SC2" ]) + assert_equal(ccn, [ "CC", "CC" ]) + + c.remove_subcircuit(sc2) + + names = [] + c.each_subcircuit { |sc| names << sc.name} + assert_equal(names, [ "SC1" ]) + + sc2 = c.create_subcircuit(cc, "SC2") + + names = [] + ccn = [] + c.each_subcircuit { |sc| names << sc.name; ccn << sc.circuit.name } + assert_equal(names, [ "SC1", "SC2" ]) + assert_equal(ccn, [ "CC", "CC" ]) + + net = c.create_net + net.name = "NET" + + sc1.connect_pin(1, net) + assert_equal(sc1.net_for_pin(1).name, "NET") + assert_equal(sc1.net_for_pin(0).inspect, "nil") + + sc2.connect_pin(0, net) + + cnames = [] + net.each_pin { |p| cnames << p.subcircuit.name + ":" + p.pin.name } + assert_equal(cnames, [ "SC1:B", "SC2:A" ]) + cnames = [] + net.each_pin { |p| cnames << p.subcircuit.name + ":" + p.pin_id.to_s } + assert_equal(cnames, [ "SC1:1", "SC2:0" ]) + net.each_pin { |p| assert_equal(p.net.name, "NET") } + + sc1.disconnect_pin(1) + assert_equal(sc1.net_for_pin(1).inspect, "nil") + + cnames = [] + net.each_pin { |p| cnames << p.subcircuit.name + ":" + p.pin.name } + assert_equal(cnames, [ "SC2:A" ]) + net.each_pin { |p| assert_equal(p.net.name, "NET") } + + net.clear + assert_equal(sc1.net_for_pin(1).inspec, "nil") + assert_equal(sc1.net_for_pin(0).inspect, "nil") + + end + + def test_5_SubCircuit + + nl = RBA::Netlist::new + + c = RBA::Circuit::new + c.name = "C" + nl.add(c) + + net = c.create_net + + assert_equal(net.circuit.name, "C") + + net.name = "NET" + assert_equal(net.name, "NET") + + net.cluster_id = 42 + assert_equal(net.cluster_id, 42) + + end + + def test_6_GenericDeviceClass + + nl = RBA::Netlist::new + + dc = RBA::GenericDeviceClass::new + nl.add(dc) + dc.name = "DC" + assert_equal(dc.name, "DC") + dc.description = "A device class" + assert_equal(dc.description, "A device class") + + pd = RBA::DevicePortDefinition::new + pd.name = "A" + pd.description = "Port A" + dc.add_port(pd) + + assert_equal(pd.id, 0) + assert_equal(pd.name, "A") + assert_equal(pd.description, "Port A") + + pd = RBA::DevicePortDefinition::new + pd.name = "B" + pd.description = "Port B" + dc.add_port(pd) + + assert_equal(pd.id, 1) + assert_equal(pd.name, "B") + assert_equal(pd.description, "Port B") + + names = [] + dc.port_definitions.each { |pd| names << pd.name } + assert_equal(names, [ "A", "B" ]) + + dc.clear_ports + + names = [] + dc.port_definitions.each { |pd| names << pd.name } + assert_equal(names, []) + + end + + def test_7_Circuit + + nl = RBA::Netlist::new + + c = RBA::Circuit::new + nl.add(c) + assert_equal(c.netlist.object_id, nl.object_id) + c.name = "C" + assert_equal(c.name, "C") + c.cell_index = 42 + assert_equal(c.cell_index, 42) + + pina1 = c.create_pin("A1") + pina2 = c.create_pin("A2") + pinb1 = c.create_pin("B1") + pinb2 = c.create_pin("B2") + assert_equal(c.pin_count, 4) + + assert_equal(pina1.id, 0) + assert_equal(pina2.id, 1) + assert_equal(pinb1.id, 2) + assert_equal(pinb2.id, 3) + assert_equal(c.pin_by_id(0).name, "A1") + assert_equal(c.pin_by_id(3).name, "B2") + + names = [] + c.each_pin { |p| names << p.name } + assert_equal(names, [ "A1", "A2", "B1", "B2" ]) + + net1 = c.create_net + net1.name = "NET1" + + net2 = c.create_net + net2.name = "NET2" + + names = [] + c.each_net { |n| names << n.name } + assert_equal(names, [ "NET1", "NET2" ]) + + c.connect_pin(pina1, net1) + c.connect_pin(pinb1.id, net1) + c.connect_pin(pina2, net2) + c.connect_pin(pinb2.id, net2) + + assert_equal(c.net_for_pin(pina1).name, "NET1") + assert_equal(c.net_for_pin(pinb1.id).name, "NET1") + assert_equal(c.net_for_pin(pina2).name, "NET2") + assert_equal(c.net_for_pin(pinb2.id).name, "NET2") + + c.disconnect_pin(pinb1.id) + c.disconnect_pin(pina2) + + assert_equal(c.net_for_pin(pina1).name, "NET1") + assert_equal(c.net_for_pin(pinb1.id).inspect, "nil") + assert_equal(c.net_for_pin(pina2).inspect, "nil") + assert_equal(c.net_for_pin(pinb2.id).name, "NET2") + + c.remove_net(net1) + + assert_equal(c.net_for_pin(pina1).inspect, "nil") + assert_equal(c.net_for_pin(pinb1.id).inspect, "nil") + assert_equal(c.net_for_pin(pina2).inspect, "nil") + assert_equal(c.net_for_pin(pinb2.id).name, "NET2") + + names = [] + c.each_net { |n| names << n.name } + assert_equal(names, [ "NET2" ]) + + c.clear + + names = [] + c.each_net { |n| names << n.name } + assert_equal(names, []) + + assert_equal(c.pin_count, 0) + end end load("test_epilogue.rb") +