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 \ dbLocalOperation.cc \
dbHierProcessor.cc \ dbHierProcessor.cc \
dbDeepRegion.cc \ dbDeepRegion.cc \
dbHierNetworkProcessor.cc dbHierNetworkProcessor.cc \
dbNetlistProperty.cc \
gsiDeclDbNetlistProperty.cc
HEADERS = \ HEADERS = \
dbArray.h \ dbArray.h \
@ -250,7 +252,8 @@ HEADERS = \
dbDeepShapeStore.h \ dbDeepShapeStore.h \
dbHierarchyBuilder.h \ dbHierarchyBuilder.h \
dbLocalOperation.h \ dbLocalOperation.h \
dbHierProcessor.h dbHierProcessor.h \
dbNetlistProperty.h
!equals(HAVE_QT, "0") { !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 \ dbHierProcessorTests.cc \
dbDeepRegionTests.cc \ dbDeepRegionTests.cc \
dbDeepShapeStoreTests.cc \ dbDeepShapeStoreTests.cc \
dbHierNetworkProcessorTests.cc dbHierNetworkProcessorTests.cc \
dbNetlistPropertyTests.cc
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
DEPENDPATH += $$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 (dbLayoutDiff, "dbLayoutDiff.rb")
RUBYTEST (dbLayoutQuery, "dbLayoutQuery.rb") RUBYTEST (dbLayoutQuery, "dbLayoutQuery.rb")
RUBYTEST (dbMatrix, "dbMatrix.rb") RUBYTEST (dbMatrix, "dbMatrix.rb")
RUBYTEST (dbNetlistProperty, "dbNetlistProperty.rb")
RUBYTEST (dbPathTest, "dbPathTest.rb") RUBYTEST (dbPathTest, "dbPathTest.rb")
RUBYTEST (dbPCells, "dbPCells.rb") RUBYTEST (dbPCells, "dbPCells.rb")
RUBYTEST (dbPointTest, "dbPointTest.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")