diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 3ac6db9e4..63b3c2fdc 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -141,7 +141,9 @@ SOURCES = \ dbLocalOperation.cc \ dbHierProcessor.cc \ dbDeepRegion.cc \ - dbHierNetworkProcessor.cc + dbHierNetworkProcessor.cc \ + dbNetlistProperty.cc \ + gsiDeclDbNetlistProperty.cc HEADERS = \ dbArray.h \ @@ -250,7 +252,8 @@ HEADERS = \ dbDeepShapeStore.h \ dbHierarchyBuilder.h \ dbLocalOperation.h \ - dbHierProcessor.h + dbHierProcessor.h \ + dbNetlistProperty.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbNetlistProperty.cc b/src/db/db/dbNetlistProperty.cc new file mode 100644 index 000000000..12e3213fa --- /dev/null +++ b/src/db/db/dbNetlistProperty.cc @@ -0,0 +1,196 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbNetlistProperty.h" +#include "tlString.h" + +#include + +namespace tl +{ + +void VariantUserClass::destroy (void *p) const +{ + delete (db::NetlistProperty *) p; +} + +bool VariantUserClass::equal (const void *a, const void *b) const +{ + const db::NetlistProperty *pa = (db::NetlistProperty *) a; + const db::NetlistProperty *pb = (db::NetlistProperty *) b; + if (typeid (*pa) == typeid (*pb)) { + return pa->equals (pb); + } else { + return false; + } +} + +bool VariantUserClass::less (const void *a, const void *b) const +{ + const db::NetlistProperty *pa = (db::NetlistProperty *) a; + const db::NetlistProperty *pb = (db::NetlistProperty *) b; + if (typeid (*pa) == typeid (*pb)) { + return pa->less (pb); + } else { + return typeid (*pa).before (typeid (*pb)); + } +} + +void *VariantUserClass::clone (const void *p) const +{ + return ((const db::NetlistProperty *) p)->clone (); +} + +std::string VariantUserClass::to_string (const void *p) const +{ + return ((const db::NetlistProperty *) p)->to_string (); +} + +void VariantUserClass::read (void *p, tl::Extractor &ex) const +{ + ((db::NetlistProperty *) p)->read (ex); +} + +void VariantUserClass::assign (void *self, const void *other) const +{ + db::NetlistProperty *pself = (db::NetlistProperty *) self; + const db::NetlistProperty *pother = (const db::NetlistProperty *) other; + tl_assert (typeid (*pself) == typeid (*pother)); + pself->assign (pother); +} + +void *VariantUserClass::deref_proxy (tl::Object *proxy) const +{ + return proxy; +} + +void VariantUserClass::register_instance (const tl::VariantUserClassBase *inst, bool is_const) +{ + VariantUserClassBase::register_instance (inst, typeid (db::NetlistProperty), is_const); +} + +void VariantUserClass::unregister_instance (const tl::VariantUserClassBase *inst, bool is_const) +{ + VariantUserClassBase::unregister_instance (inst, typeid (db::NetlistProperty), is_const); +} + +} + +namespace db +{ + +// -------------------------------------------------------------------------------------------- +// NetlistProperty Implementation + +NetlistProperty::NetlistProperty () +{ + // .. nothing yet .. +} + +NetlistProperty::NetlistProperty (const NetlistProperty &) +{ + // .. nothing yet .. +} + +NetlistProperty::~NetlistProperty () +{ + // .. nothing yet .. +} + +const tl::VariantUserClass *NetlistProperty::variant_class () +{ + static tl::VariantUserClass s_cls; + return &s_cls; +} + +// -------------------------------------------------------------------------------------------- +// NetlistName Implementation + +NetNameProperty::NetNameProperty () + : NetlistProperty () +{ + // .. nothing yet .. +} + +NetNameProperty::NetNameProperty (const NetNameProperty &other) + : NetlistProperty (other), m_name (other.m_name) +{ + // .. nothing yet .. +} + +NetNameProperty::NetNameProperty (const std::string &n) + : NetlistProperty (), m_name (n) +{ + // .. nothing yet .. +} + +NetNameProperty &NetNameProperty::operator= (const NetNameProperty &other) +{ + NetlistProperty::operator= (other); + if (this != &other) { + m_name = other.m_name; + } + return *this; +} + +void NetNameProperty::set_name (const std::string &n) +{ + m_name = n; +} + +bool NetNameProperty::equals (const NetlistProperty *p) const +{ + const NetNameProperty *pp = static_cast (p); + return NetlistProperty::equals (p) && m_name == pp->m_name; +} + +bool NetNameProperty::less (const NetlistProperty *p) const +{ + if (! NetlistProperty::equals (p)) { + return NetlistProperty::less (p); + } else { + const NetNameProperty *pp = static_cast (p); + return m_name < pp->m_name; + } +} + +void NetNameProperty::assign (const NetlistProperty *p) +{ + NetlistProperty::assign (p); + const NetNameProperty *pp = static_cast (p); + m_name = pp->m_name; +} + + +static const char *valid_netname_chars = "_.$[]():-,"; + +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) +{ + ex.read_word_or_quoted (m_name, valid_netname_chars); +} + +} diff --git a/src/db/db/dbNetlistProperty.h b/src/db/db/dbNetlistProperty.h new file mode 100644 index 000000000..efb41136a --- /dev/null +++ b/src/db/db/dbNetlistProperty.h @@ -0,0 +1,235 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbCommon.h" +#include "tlVariant.h" + +#include + +namespace db +{ + class NetlistProperty; +} + +namespace tl +{ + class Extractor; + + // specialization of tl::VariantUserClass for the purpose of NetlistProperty representation + template <> class DB_PUBLIC tl::VariantUserClass + : public tl::VariantUserClassBase + { + public: + // creation not supported + virtual void *create () const { tl_assert (false); } + + virtual void destroy (void *p) const; + virtual bool equal (const void *a, const void *b) const; + virtual bool less (const void *a, const void *b) const; + virtual void *clone (const void *p) const; + virtual const char *name () const { return ""; } + virtual bool is_const () const { return false; } + virtual const gsi::ClassBase *gsi_cls () const { return 0; } + virtual const tl::EvalClass *eval_cls () const { return 0; } + virtual std::string to_string (const void *p) const; + virtual void read (void *p, tl::Extractor &ex) const; + virtual void assign (void *self, const void *other) const; + virtual void *deref_proxy (tl::Object *proxy) const; + + db::NetlistProperty *get (void *ptr) const { return reinterpret_cast (ptr); } + const db::NetlistProperty *get (const void *ptr) const { return reinterpret_cast (ptr); } + + protected: + void register_instance (const tl::VariantUserClassBase *inst, bool is_const); + void unregister_instance (const tl::VariantUserClassBase *inst, bool is_const); + }; + +} + +namespace db +{ + +/** + * @brief The base class for a netlist property attached to a shape + * + * This class provides a wrapper for binding a netlist property + * to a tl::Variant. Hence it can be kept as a shape property + * in the context of db::Layout's propery repo. + */ +class DB_PUBLIC NetlistProperty +{ +public: + /** + * @brief Gets the class descriptor for keeping the object inside a tl::Variant + * + * For a Variant that owns a NetlistProperty object, use + * + * @code + * db::NetlistProperty *prop = new db::NetlistProperty (); + * bool shared = true; // the variant will own the object + * tl::Variant prop_in_var (prop, prop->variant_class (), shared); + * @endcode + */ + static const tl::VariantUserClass *variant_class (); + + /** + * @brief Constructor + */ + NetlistProperty (); + + /** + * @brief Copy constructor + */ + NetlistProperty (const NetlistProperty &other); + + /** + * @brief (virtual) Destructor + */ + virtual ~NetlistProperty (); + + /** + * @brief Clones the object + */ + virtual NetlistProperty *clone () const + { + return new NetlistProperty (*this); + } + + /** + * @brief Compares two objects (equal). Both types are guaranteed to be the same. + */ + virtual bool equals (const NetlistProperty *) const + { + return true; + } + + /** + * @brief Compares two objects (less). Both types are guaranteed to be the same. + */ + virtual bool less (const NetlistProperty *) const + { + return false; + } + + /** + * @brief Assigned the other object to self. Both types are guaranteed to be identical. + */ + virtual void assign (const NetlistProperty *) + { + // .. nothing yet .. + } + + /** + * @brief Converts to a string + */ + virtual std::string to_string () const + { + return std::string (); + } + + /** + * @brief Pulls the object from a string + */ + virtual void read (tl::Extractor &) + { + // .. nothing yet .. + } +}; + +/** + * @brief A property meaning a net name + */ +class DB_PUBLIC NetNameProperty + : public db::NetlistProperty +{ +public: + /** + * @brief Creates a netlist name property without a specific name + */ + NetNameProperty (); + + /** + * @brief copy constructor + */ + NetNameProperty (const NetNameProperty &other); + + /** + * @brief Creates a netlist name property with the given name + */ + NetNameProperty (const std::string &n); + + /** + * @brief Assignment + */ + NetNameProperty &operator= (const NetNameProperty &other); + + /** + * @brief Sets the name + */ + void set_name (const std::string &n); + + /** + * @brief Gets the name + */ + const std::string &name () const + { + return m_name; + } + + /** + * @brief Clones the object + */ + virtual NetlistProperty *clone () const + { + return new NetNameProperty (*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; + + /** + * @brief Pulls the object from a string + */ + virtual void read (tl::Extractor &); + +private: + std::string m_name; +}; + +} diff --git a/src/db/db/gsiDeclDbNetlistProperty.cc b/src/db/db/gsiDeclDbNetlistProperty.cc new file mode 100644 index 000000000..30b4de22f --- /dev/null +++ b/src/db/db/gsiDeclDbNetlistProperty.cc @@ -0,0 +1,116 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "gsiDecl.h" +#include "dbNetlistProperty.h" + +namespace gsi +{ + +// --------------------------------------------------------------- +// db::NetlistProperty binding + +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" + ), + "@brief A generic base class for netlist properties.\n" + "\n" + "Netlist properties are used to annotate shapes or other objects with net properties. " + "Netlist properties are net names or device ports. " + "Netlist properties can be stored inside property sets. " + "This class provides the base class for such netlist properties." + "\n\n" + "This class was introduced in version 0.26.\n" +); + +// --------------------------------------------------------------- +// db::NetNameProperty binding + +static db::NetNameProperty *new_netname () +{ + return new db::NetNameProperty (); +} + +static db::NetNameProperty *new_netname2 (const std::string &n) +{ + return new db::NetNameProperty (n); +} + +gsi::Class decl_NetNameProperty (decl_NetlistProperty, "db", "NetNameProperty", + gsi::constructor ("new", &new_netname, + "@brief Creates a new net name property object without a specific name" + ) + + gsi::constructor ("new", &new_netname2, gsi::arg ("name"), + "@brief Creates a new net name property object with the given name" + ) + + gsi::method ("name=", &db::NetNameProperty::set_name, gsi::arg ("n"), + "@brief Sets the name\n" + ) + + gsi::method ("name", &db::NetNameProperty::name, + "@brief Gets the name\n" + ), + "@brief A net name property.\n" + "\n" + "The netlist property annotates a shape or other object with a net name." + "\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 new file mode 100644 index 000000000..7f82e8072 --- /dev/null +++ b/src/db/unit_tests/dbNetlistPropertyTests.cc @@ -0,0 +1,69 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbNetlistProperty.h" + +#include "tlUnitTest.h" +#include "tlVariant.h" + +#include + +TEST(1_Basic) +{ + db::NetNameProperty name; + EXPECT_EQ (name.to_string (), "name:''"); + + name.set_name ("abc"); + EXPECT_EQ (name.to_string (), "name:abc"); + EXPECT_EQ (name.name (), "abc"); + + db::NetNameProperty n2 = name; + EXPECT_EQ (n2.name (), "abc"); + + n2 = db::NetNameProperty ("xyz"); + EXPECT_EQ (n2.name (), "xyz"); + + 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) +{ + std::auto_ptr nn (new db::NetNameProperty ()); + nn->set_name ("net42"); + + tl::Variant v (nn.release (), db::NetlistProperty::variant_class (), true); + EXPECT_EQ (v.is_user (), true); + EXPECT_EQ (dynamic_cast(v.to_user ()).name (), "net42"); + EXPECT_EQ (v.to_string (), "name:net42"); + + tl::Variant vv = v; + v = tl::Variant (); + EXPECT_EQ (v.is_user (), false); + EXPECT_EQ (vv.is_user (), true); + EXPECT_EQ (dynamic_cast(vv.to_user ()).name (), "net42"); +} diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index 052a65b78..f67e2f202 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -58,7 +58,8 @@ SOURCES = \ dbHierProcessorTests.cc \ dbDeepRegionTests.cc \ dbDeepShapeStoreTests.cc \ - dbHierNetworkProcessorTests.cc + dbHierNetworkProcessorTests.cc \ + dbNetlistPropertyTests.cc INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC diff --git a/src/rba/unit_tests/rba.cc b/src/rba/unit_tests/rba.cc index d5acbf36c..e6d7dcac7 100644 --- a/src/rba/unit_tests/rba.cc +++ b/src/rba/unit_tests/rba.cc @@ -109,6 +109,7 @@ RUBYTEST (dbLayoutTest, "dbLayoutTest.rb") RUBYTEST (dbLayoutDiff, "dbLayoutDiff.rb") RUBYTEST (dbLayoutQuery, "dbLayoutQuery.rb") RUBYTEST (dbMatrix, "dbMatrix.rb") +RUBYTEST (dbNetlistProperty, "dbNetlistProperty.rb") RUBYTEST (dbPathTest, "dbPathTest.rb") RUBYTEST (dbPCells, "dbPCells.rb") RUBYTEST (dbPointTest, "dbPointTest.rb") diff --git a/testdata/ruby/dbNetlistProperty.rb b/testdata/ruby/dbNetlistProperty.rb new file mode 100644 index 000000000..c7dae4292 --- /dev/null +++ b/testdata/ruby/dbNetlistProperty.rb @@ -0,0 +1,81 @@ +# encoding: UTF-8 + +# KLayout Layout Viewer +# Copyright (C) 2006-2018 Matthias Koefferlein +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +if !$:.member?(File::dirname($0)) + $:.push(File::dirname($0)) +end + +load("test_prologue.rb") + +class DBNetlistProperty_TestClass < TestBase + + def test_1_Basic + + np = RBA::NetlistProperty::new + 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 + + np = RBA::NetNameProperty::new + assert_equal(np.is_a?(RBA::NetlistProperty), true) + assert_equal(np.is_a?(RBA::NetNameProperty), true) + assert_equal(np.to_s, "name:''") + + np.name = "abc" + 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_VariantBinding + + ly = RBA::Layout::new + l1 = ly.insert_layer(RBA::LayerInfo::new(1, 0)) + tc = ly.create_cell("TOP") + shapes = tc.shapes(l1) + + box = shapes.insert(RBA::Box::new(0, 0, 1000, 2000)) + + # dry run + box.set_property("a", 17) + assert_equal(box.property("a"), 17) + + # set a NetNameProperty: + box.set_property("nn", RBA::NetNameProperty::new("net42")) + nn = box.property("nn") + assert_equal(nn.is_a?(RBA::NetlistProperty), true) + assert_equal(nn.is_a?(RBA::NetNameProperty), true) + assert_equal(nn.name, "net42") + + end + +end + +load("test_epilogue.rb")