WIP: netlist property framework

- NetlistProperty is the base class for objects that can
  be attached to shapes for annotation
- First property type implemented: net name is a way
  to annotate net names
This commit is contained in:
Matthias Koefferlein 2018-12-18 23:56:01 +01:00
parent c10dfee984
commit 2c4e84fdf2
8 changed files with 705 additions and 3 deletions

View File

@ -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") {

View File

@ -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 <typeinfo>
namespace tl
{
void VariantUserClass<db::NetlistProperty>::destroy (void *p) const
{
delete (db::NetlistProperty *) p;
}
bool VariantUserClass<db::NetlistProperty>::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<db::NetlistProperty>::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<db::NetlistProperty>::clone (const void *p) const
{
return ((const db::NetlistProperty *) p)->clone ();
}
std::string VariantUserClass<db::NetlistProperty>::to_string (const void *p) const
{
return ((const db::NetlistProperty *) p)->to_string ();
}
void VariantUserClass<db::NetlistProperty>::read (void *p, tl::Extractor &ex) const
{
((db::NetlistProperty *) p)->read (ex);
}
void VariantUserClass<db::NetlistProperty>::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<db::NetlistProperty>::deref_proxy (tl::Object *proxy) const
{
return proxy;
}
void VariantUserClass<db::NetlistProperty>::register_instance (const tl::VariantUserClassBase *inst, bool is_const)
{
VariantUserClassBase::register_instance (inst, typeid (db::NetlistProperty), is_const);
}
void VariantUserClass<db::NetlistProperty>::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<db::NetlistProperty> *NetlistProperty::variant_class ()
{
static tl::VariantUserClass<db::NetlistProperty> 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<const NetNameProperty *> (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<const NetNameProperty *> (p);
return m_name < pp->m_name;
}
}
void NetNameProperty::assign (const NetlistProperty *p)
{
NetlistProperty::assign (p);
const NetNameProperty *pp = static_cast<const NetNameProperty *> (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);
}
}

View File

@ -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 <string>
namespace db
{
class NetlistProperty;
}
namespace tl
{
class Extractor;
// specialization of tl::VariantUserClass for the purpose of NetlistProperty representation
template <> class DB_PUBLIC tl::VariantUserClass<db::NetlistProperty>
: 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<db::NetlistProperty *> (ptr); }
const db::NetlistProperty *get (const void *ptr) const { return reinterpret_cast<const db::NetlistProperty *> (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<db::NetlistProperty> *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;
};
}

View File

@ -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<db::NetNameProperty> n (new db::NetNameProperty ());
n->read (ex);
return n.release ();
} else {
return 0;
}
}
gsi::Class<db::NetlistProperty> 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<db::NetNameProperty> 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"
);
}

View File

@ -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 <memory>
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<db::NetNameProperty> nn (new db::NetNameProperty ());
nn->set_name ("net42");
tl::Variant v (nn.release (), db::NetlistProperty::variant_class (), true);
EXPECT_EQ (v.is_user<db::NetlistProperty> (), true);
EXPECT_EQ (dynamic_cast<db::NetNameProperty &>(v.to_user<db::NetlistProperty> ()).name (), "net42");
EXPECT_EQ (v.to_string (), "name:net42");
tl::Variant vv = v;
v = tl::Variant ();
EXPECT_EQ (v.is_user<db::NetlistProperty> (), false);
EXPECT_EQ (vv.is_user<db::NetlistProperty> (), true);
EXPECT_EQ (dynamic_cast<db::NetNameProperty &>(vv.to_user<db::NetlistProperty> ()).name (), "net42");
}

View File

@ -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

View File

@ -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")

81
testdata/ruby/dbNetlistProperty.rb vendored Normal file
View File

@ -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")