From c5222c26e3cbb0725d690ad57e9642641f633f5b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 24 Dec 2018 01:31:06 +0100 Subject: [PATCH] Added DevicePortProperty class with tests and GSI binding --- src/db/db/dbNetlist.h | 38 +++++++ src/db/db/dbNetlistProperty.cc | 74 ++++++++++++- src/db/db/dbNetlistProperty.h | 109 ++++++++++++-------- src/db/db/gsiDeclDbNetlist.cc | 5 +- src/db/db/gsiDeclDbNetlistProperty.cc | 60 ++++++----- src/db/unit_tests/dbNetlistPropertyTests.cc | 28 +++-- src/db/unit_tests/dbNetlistTests.cc | 28 +++++ testdata/ruby/dbNetlist.rb | 14 ++- testdata/ruby/dbNetlistProperty.rb | 36 +++++-- 9 files changed, 291 insertions(+), 101 deletions(-) diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index 432ec77a2..d1553bdcf 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -75,6 +75,25 @@ public: */ NetPortRef &operator= (const NetPortRef &other); + /** + * @brief Comparison + */ + bool operator< (const NetPortRef &other) const + { + if (mp_device != other.mp_device) { + return mp_device < other.mp_device; + } + return m_port_id < other.m_port_id; + } + + /** + * @brief Equality + */ + bool operator== (const NetPortRef &other) const + { + return (mp_device == other.mp_device && m_port_id == other.m_port_id); + } + /** * @brief Gets the device reference */ @@ -178,6 +197,25 @@ public: */ NetPinRef &operator= (const NetPinRef &other); + /** + * @brief Comparison + */ + bool operator< (const NetPinRef &other) const + { + if (mp_subcircuit != other.mp_subcircuit) { + return mp_subcircuit < other.mp_subcircuit; + } + return m_pin_id < other.m_pin_id; + } + + /** + * @brief Equality + */ + bool operator== (const NetPinRef &other) const + { + return (mp_subcircuit == other.mp_subcircuit && m_pin_id == other.m_pin_id); + } + /** * @brief Gets the pin reference (const version) */ diff --git a/src/db/db/dbNetlistProperty.cc b/src/db/db/dbNetlistProperty.cc index 12e3213fa..27757bede 100644 --- a/src/db/db/dbNetlistProperty.cc +++ b/src/db/db/dbNetlistProperty.cc @@ -65,9 +65,10 @@ std::string VariantUserClass::to_string (const void *p) con return ((const db::NetlistProperty *) p)->to_string (); } -void VariantUserClass::read (void *p, tl::Extractor &ex) const +void VariantUserClass::read (void * /*p*/, tl::Extractor & /*ex*/) const { - ((db::NetlistProperty *) p)->read (ex); + // .. nothing yet .. + return; } void VariantUserClass::assign (void *self, const void *other) const @@ -123,7 +124,7 @@ const tl::VariantUserClass *NetlistProperty::variant_class } // -------------------------------------------------------------------------------------------- -// NetlistName Implementation +// NetNameProperty Implementation NetNameProperty::NetNameProperty () : NetlistProperty () @@ -188,9 +189,72 @@ std::string NetNameProperty::to_string () const return "name:" + tl::to_word_or_quoted_string (m_name, valid_netname_chars); } -void NetNameProperty::read (tl::Extractor &ex) +// -------------------------------------------------------------------------------------------- +// DevicePortProperty Implementation + +DevicePortProperty::DevicePortProperty () + : NetlistProperty () { - ex.read_word_or_quoted (m_name, valid_netname_chars); + // .. nothing yet .. +} + +DevicePortProperty::DevicePortProperty (const DevicePortProperty &other) + : NetlistProperty (other), m_port_ref (other.m_port_ref) +{ + // .. nothing yet .. +} + +DevicePortProperty::DevicePortProperty (const db::NetPortRef &p) + : NetlistProperty (), m_port_ref (p) +{ + // .. nothing yet .. +} + +DevicePortProperty &DevicePortProperty::operator= (const DevicePortProperty &other) +{ + NetlistProperty::operator= (other); + if (this != &other) { + m_port_ref = other.m_port_ref; + } + return *this; +} + +void DevicePortProperty::set_port_ref (const db::NetPortRef &p) +{ + m_port_ref = p; +} + +bool DevicePortProperty::equals (const NetlistProperty *p) const +{ + const DevicePortProperty *pp = static_cast (p); + return NetlistProperty::equals (p) && m_port_ref == pp->m_port_ref; +} + +bool DevicePortProperty::less (const NetlistProperty *p) const +{ + if (! NetlistProperty::equals (p)) { + return NetlistProperty::less (p); + } else { + const DevicePortProperty *pp = static_cast (p); + return m_port_ref < pp->m_port_ref; + } +} + +void DevicePortProperty::assign (const NetlistProperty *p) +{ + NetlistProperty::assign (p); + const DevicePortProperty *pp = static_cast (p); + m_port_ref = pp->m_port_ref; +} + + +std::string DevicePortProperty::to_string () const +{ + if (m_port_ref.device () && m_port_ref.port_def ()) { + return "port:" + tl::to_word_or_quoted_string (m_port_ref.device ()->name ()) + ":" + tl::to_word_or_quoted_string (m_port_ref.port_def ()->name ()); + } else { + return "port"; + } } } diff --git a/src/db/db/dbNetlistProperty.h b/src/db/db/dbNetlistProperty.h index 76c47bd40..8e8e6bd47 100644 --- a/src/db/db/dbNetlistProperty.h +++ b/src/db/db/dbNetlistProperty.h @@ -149,14 +149,6 @@ public: { return std::string (); } - - /** - * @brief Pulls the object from a string - */ - virtual void read (tl::Extractor &) - { - // .. nothing yet .. - } }; /** @@ -227,59 +219,86 @@ public: */ virtual std::string to_string () const; - /** - * @brief Pulls the object from a string - */ - virtual void read (tl::Extractor &); - private: std::string m_name; }; -#if 0 // @@@ /** - * @brief A reference to an actual port - */ -class DB_PUBLIC DevicePortRef - : public db::NetlistProperty -{ -public: - DevicePortRef (db::NetPortRef *port); - - // ... - -private: - tl::weak_ptr mp_port; -}; - -/** - * @brief An abstrace reference to a port + * @brief A reference to a device port * - * Abstract references are created when turning a string back into a port. - * Abstract references can be turned into actual port references using - * "to_actual_ref". + * This property is used to mark a shape as a device port reference. + * Such a port reference points to a port of a specific device. + * Attaching such a property to a shape allows connecting the + * net to the device later. */ -class DB_PUBLIC DevicePortAbstractRef +class DB_PUBLIC DevicePortProperty : public db::NetlistProperty { public: - DevicePortAbstractRef (const std::string &device_name, const std::string &port_name); - - // ... + /** + * @brief Creates a netlist name property without a specific name + */ + DevicePortProperty (); /** - * @brief Turns an abstract reference into an actual one - * - * The returned object is either 0, if the translation cannot be done or - * and new'd NetPortRef object. It's the responsibility of the caller - * to delete this object when it's no longer used. + * @brief copy constructor */ - NetPortRef *to_actual_ref (const db::Netlist *netlist) const; + DevicePortProperty (const db::DevicePortProperty &other); + + /** + * @brief Creates a netlist name property with the given name + */ + DevicePortProperty (const db::NetPortRef &port_ref); + + /** + * @brief Assignment + */ + DevicePortProperty &operator= (const DevicePortProperty &other); + + /** + * @brief Sets the port reference + */ + void set_port_ref (const db::NetPortRef &port_ref); + + /** + * @brief Gets the port reference + */ + const db::NetPortRef &port_ref () const + { + return m_port_ref; + } + + /** + * @brief Clones the object + */ + virtual DevicePortProperty *clone () const + { + return new DevicePortProperty (*this); + } + + /** + * @brief Compares two objects (equal). Both types are guaranteed to be the same. + */ + virtual bool equals (const NetlistProperty *) const; + + /** + * @brief Compares two objects (less). Both types are guaranteed to be the same. + */ + virtual bool less (const NetlistProperty *) const; + + /** + * @brief Assigned the other object to self. Both types are guaranteed to be identical. + */ + virtual void assign (const NetlistProperty *); + + /** + * @brief Converts to a string + */ + virtual std::string to_string () const; private: - std::string m_device_name, m_port_name; + db::NetPortRef m_port_ref; }; -#endif } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 37e77fd57..77f66a39c 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -332,10 +332,11 @@ static const db::Pin &create_pin (db::Circuit *c, const std::string &name) return c->add_pin (db::Pin (name)); } -static db::Net *create_net (db::Circuit *c) +static db::Net *create_net (db::Circuit *c, const std::string &name) { db::Net *n = new db::Net (); c->add_net (n); + n->set_name (name); return n; } @@ -394,7 +395,7 @@ Class decl_dbCircuit ("db", "Circuit", gsi::method ("pin_count", &db::Circuit::pin_count, "@brief Gets the number of pins in the circuit" ) + - gsi::method_ext ("create_net", &gsi::create_net, + gsi::method_ext ("create_net", &gsi::create_net, gsi::arg ("name", std::string ()), "@brief Creates a new \\Net object inside the circuit\n" "This object will describe a net of the circuit. The nets are basically " "connections between the different components of the circuit (subcircuits, " diff --git a/src/db/db/gsiDeclDbNetlistProperty.cc b/src/db/db/gsiDeclDbNetlistProperty.cc index 30b4de22f..b4a2fa80c 100644 --- a/src/db/db/gsiDeclDbNetlistProperty.cc +++ b/src/db/db/gsiDeclDbNetlistProperty.cc @@ -35,37 +35,10 @@ static db::NetlistProperty *new_property () return new db::NetlistProperty (); } -static db::NetlistProperty *from_string (const std::string &str) -{ - tl::Extractor ex (str.c_str ()); - if (ex.at_end ()) { - - return new db::NetlistProperty (); - - } else if (ex.test ("name")) { - - ex.test (":"); - std::auto_ptr n (new db::NetNameProperty ()); - n->read (ex); - return n.release (); - - } else { - - return 0; - - } -} - gsi::Class decl_NetlistProperty ("db", "NetlistProperty", gsi::constructor ("new", &new_property, "@brief Creates a plain netlist property" ) + - gsi::constructor ("from_s", &from_string, gsi::arg ("str"), - "@brief Creates a netlist property from a string\n" - "This method can turn the string returned by \\to_string back into a property object.\n" - "@param str The string to read the property from\n" - "@return A fresh property object created from the string\n" - ) + gsi::method ("to_s", &db::NetlistProperty::to_string, "@brief Convert the property to a string.\n" "@return The string representing this property\n" @@ -113,4 +86,37 @@ gsi::Class decl_NetNameProperty (decl_NetlistProperty, "db" "This class was introduced in version 0.26.\n" ); +// --------------------------------------------------------------- +// db::DevicePortProperty binding + +static db::DevicePortProperty *new_devport () +{ + return new db::DevicePortProperty (); +} + +static db::DevicePortProperty *new_devport2 (const db::NetPortRef &n) +{ + return new db::DevicePortProperty (n); +} + +gsi::Class decl_DevicePortProperty (decl_NetlistProperty, "db", "DevicePortProperty", + gsi::constructor ("new", &new_devport, + "@brief Creates a new device port property" + ) + + gsi::constructor ("new", &new_devport2, gsi::arg ("port_ref"), + "@brief Creates a new device port property with the given port reference" + ) + + gsi::method ("port_ref=", &db::DevicePortProperty::set_port_ref, gsi::arg ("p"), + "@brief Sets the port reference\n" + ) + + gsi::method ("port_ref", &db::DevicePortProperty::port_ref, + "@brief Gets the port reference\n" + ), + "@brief A device port reference property.\n" + "\n" + "The netlist property annotates a shape or other object with a reference to a device port." + "\n\n" + "This class was introduced in version 0.26.\n" +); + } diff --git a/src/db/unit_tests/dbNetlistPropertyTests.cc b/src/db/unit_tests/dbNetlistPropertyTests.cc index 7f82e8072..aca2afcc7 100644 --- a/src/db/unit_tests/dbNetlistPropertyTests.cc +++ b/src/db/unit_tests/dbNetlistPropertyTests.cc @@ -28,7 +28,7 @@ #include -TEST(1_Basic) +TEST(1_NameBasic) { db::NetNameProperty name; EXPECT_EQ (name.to_string (), "name:''"); @@ -45,13 +45,28 @@ TEST(1_Basic) n2.set_name ("\"quoted\""); EXPECT_EQ (n2.to_string (), "name:'\"quoted\"'"); - - tl::Extractor ex ("net42"); - n2.read (ex); - EXPECT_EQ (n2.name (), "net42"); } -TEST(2_Variants) +TEST(2_PortRefBasic) +{ + db::GenericDeviceClass dc; + dc.add_port_definition (db::DevicePortDefinition ("A", "Port A")); + dc.add_port_definition (db::DevicePortDefinition ("B", "Port B")); + + db::Device d (&dc, "D"); + + db::DevicePortProperty dp (db::NetPortRef (&d, 1)); + EXPECT_EQ (dp.to_string (), "port:D:B"); + + dp.set_port_ref (db::NetPortRef (&d, 0)); + EXPECT_EQ (dp.to_string (), "port:D:A"); + EXPECT_EQ (dp.port_ref () == db::NetPortRef (&d, 0), true); + + db::DevicePortProperty dp2 = dp; + EXPECT_EQ (dp2.to_string (), "port:D:A"); +} + +TEST(3_Variants) { std::auto_ptr nn (new db::NetNameProperty ()); nn->set_name ("net42"); @@ -67,3 +82,4 @@ TEST(2_Variants) EXPECT_EQ (vv.is_user (), true); EXPECT_EQ (dynamic_cast(vv.to_user ()).name (), "net42"); } + diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index c6e5e7b43..c5da7a144 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -661,3 +661,31 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (sc2->net_for_pin (0), n2); EXPECT_EQ (sc2->net_for_pin (1), 0); } + +TEST(9_NetPortRefBasics) +{ + db::Device d1, d2; + + EXPECT_EQ (db::NetPortRef (&d1, 0) == db::NetPortRef (&d1, 0), true); + EXPECT_EQ (db::NetPortRef (&d1, 0) == db::NetPortRef (&d1, 1), false); + EXPECT_EQ (db::NetPortRef (&d1, 0) == db::NetPortRef (&d2, 0), false); + + EXPECT_EQ (db::NetPortRef (&d1, 0) < db::NetPortRef (&d1, 0), false); + EXPECT_EQ (db::NetPortRef (&d1, 0) < db::NetPortRef (&d1, 1), true); + EXPECT_EQ (db::NetPortRef (&d1, 1) < db::NetPortRef (&d1, 0), false); + EXPECT_NE ((db::NetPortRef (&d1, 0) < db::NetPortRef (&d2, 0)), (db::NetPortRef (&d2, 0) < db::NetPortRef (&d1, 0))); +} + +TEST(10_NetPinRefBasics) +{ + db::SubCircuit d1, d2; + + EXPECT_EQ (db::NetPinRef (&d1, 0) == db::NetPinRef (&d1, 0), true); + EXPECT_EQ (db::NetPinRef (&d1, 0) == db::NetPinRef (&d1, 1), false); + EXPECT_EQ (db::NetPinRef (&d1, 0) == db::NetPinRef (&d2, 0), false); + + EXPECT_EQ (db::NetPinRef (&d1, 0) < db::NetPinRef (&d1, 0), false); + EXPECT_EQ (db::NetPinRef (&d1, 0) < db::NetPinRef (&d1, 1), true); + EXPECT_EQ (db::NetPinRef (&d1, 1) < db::NetPinRef (&d1, 0), false); + EXPECT_NE ((db::NetPinRef (&d1, 0) < db::NetPinRef (&d2, 0)), (db::NetPinRef (&d2, 0) < db::NetPinRef (&d1, 0))); +} diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index 5ab05a419..87b07519e 100644 --- a/testdata/ruby/dbNetlist.rb +++ b/testdata/ruby/dbNetlist.rb @@ -180,8 +180,7 @@ class DBNetlist_TestClass < TestBase assert_equal(names, [ "D1", "D2" ]) assert_equal(dcs, [ "DC", "DC" ]) - net = c.create_net - net.name = "NET" + net = c.create_net("NET") d1.connect_port(1, net) assert_equal(d1.net_for_port(1).name, "NET") @@ -257,8 +256,7 @@ class DBNetlist_TestClass < TestBase assert_equal(names, [ "SC1", "SC2" ]) assert_equal(ccn, [ "CC", "CC" ]) - net = c.create_net - net.name = "NET" + net = c.create_net("NET") sc1.connect_pin(1, net) assert_equal(sc1.net_for_pin(1).name, "NET") @@ -283,12 +281,12 @@ class DBNetlist_TestClass < TestBase 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(1).inspect, "nil") assert_equal(sc1.net_for_pin(0).inspect, "nil") end - def test_5_SubCircuit + def test_6_SubCircuitBasic nl = RBA::Netlist::new @@ -308,7 +306,7 @@ class DBNetlist_TestClass < TestBase end - def test_6_GenericDeviceClass + def test_7_GenericDeviceClass nl = RBA::Netlist::new @@ -349,7 +347,7 @@ class DBNetlist_TestClass < TestBase end - def test_7_Circuit + def test_8_Circuit nl = RBA::Netlist::new diff --git a/testdata/ruby/dbNetlistProperty.rb b/testdata/ruby/dbNetlistProperty.rb index c7dae4292..49bee637c 100644 --- a/testdata/ruby/dbNetlistProperty.rb +++ b/testdata/ruby/dbNetlistProperty.rb @@ -31,9 +31,6 @@ class DBNetlistProperty_TestClass < TestBase assert_equal(np.is_a?(RBA::NetlistProperty), true) assert_equal(np.to_s, "") - np2 = RBA::NetlistProperty::from_s("") - assert_equal(np2.is_a?(RBA::NetlistProperty), true) - end def test_2_NetName @@ -47,14 +44,37 @@ class DBNetlistProperty_TestClass < TestBase assert_equal(np.to_s, "name:abc") assert_equal(np.name, "abc") - np2 = RBA::NetlistProperty::from_s("name:xyz") - assert_equal(np2.is_a?(RBA::NetlistProperty), true) - assert_equal(np2.is_a?(RBA::NetNameProperty), true) - assert_equal(np2.name, "xyz") + end + + def test_3_DevicePort + + np = RBA::DevicePortProperty::new + assert_equal(np.is_a?(RBA::DevicePortProperty), true) + assert_equal(np.is_a?(RBA::DevicePortProperty), true) + assert_equal(np.to_s, "port") + + dc = RBA::GenericDeviceClass::new + dp = RBA::DevicePortDefinition::new + dp.name = "A" + dc.add_port(dp) + dp.name = "B" + dc.add_port(dp) + + c = RBA::Circuit::new + d = c.create_device(dc, "D") + + n = c.create_net("NET") + d.connect_port(0, n) + + # there is no other way to produce a NetPortRef object yet + n.each_port { |p| np.port_ref = p } + + assert_equal(np.to_s, "port:D:A") + assert_equal(np.port_ref.device.name, "D") end - def test_3_VariantBinding + def test_4_VariantBinding ly = RBA::Layout::new l1 = ly.insert_layer(RBA::LayerInfo::new(1, 0))