WIP: refactoring of the netlist property thing. Now it's internal and there is only the device terminal property. The property also does not store device pointers but just IDs

This commit is contained in:
Matthias Koefferlein 2018-12-27 01:27:58 +01:00
parent f5071d3254
commit 62ffcd38e6
9 changed files with 56 additions and 434 deletions

View File

@ -143,7 +143,6 @@ SOURCES = \
dbDeepRegion.cc \
dbHierNetworkProcessor.cc \
dbNetlistProperty.cc \
gsiDeclDbNetlistProperty.cc \
dbNetlist.cc \
gsiDeclDbNetlist.cc \
dbNetlistDeviceClasses.cc \

View File

@ -217,7 +217,7 @@ void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id
// Build a property set for the DeviceTerminalProperty
db::PropertiesRepository::properties_set ps;
tl::Variant &v = ps.insert (std::make_pair (m_propname_id, tl::Variant ()))->second;
v = tl::Variant (new db::DeviceTerminalProperty (db::NetTerminalRef (device, terminal_id)), db::NetlistProperty::variant_class (), true);
v = tl::Variant (new db::DeviceTerminalProperty (device->id (), terminal_id), db::NetlistProperty::variant_class (), true);
db::properties_id_type pi = mp_layout->properties_repository ().properties_id (ps);
db::PolygonRef pr (polygon, mp_layout->shape_repository ());

View File

@ -123,111 +123,47 @@ const tl::VariantUserClass<db::NetlistProperty> *NetlistProperty::variant_class
return &s_cls;
}
// --------------------------------------------------------------------------------------------
// NetNameProperty 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);
}
// --------------------------------------------------------------------------------------------
// DeviceTerminalProperty Implementation
DeviceTerminalProperty::DeviceTerminalProperty ()
: NetlistProperty ()
: NetlistProperty (), m_terminal_id (0), m_device_id (0)
{
// .. nothing yet ..
}
DeviceTerminalProperty::DeviceTerminalProperty (const DeviceTerminalProperty &other)
: NetlistProperty (other), m_terminal_ref (other.m_terminal_ref)
: NetlistProperty (other), m_terminal_id (other.m_terminal_id), m_device_id (other.m_device_id)
{
// .. nothing yet ..
}
DeviceTerminalProperty::DeviceTerminalProperty (const db::NetTerminalRef &p)
: NetlistProperty (), m_terminal_ref (p)
DeviceTerminalProperty::DeviceTerminalProperty (size_t device_id, size_t terminal_id)
: NetlistProperty (), m_terminal_id (terminal_id), m_device_id (device_id)
{
// .. nothing yet ..
}
void DeviceTerminalProperty::set_terminal_ref (size_t device_id, size_t terminal_id)
{
m_device_id = device_id;
m_terminal_id = terminal_id;
}
DeviceTerminalProperty &DeviceTerminalProperty::operator= (const DeviceTerminalProperty &other)
{
NetlistProperty::operator= (other);
if (this != &other) {
m_terminal_ref = other.m_terminal_ref;
m_terminal_id = other.m_terminal_id;
m_device_id = other.m_device_id;
}
return *this;
}
void DeviceTerminalProperty::set_terminal_ref (const db::NetTerminalRef &p)
{
m_terminal_ref = p;
}
bool DeviceTerminalProperty::equals (const NetlistProperty *p) const
{
const DeviceTerminalProperty *pp = static_cast<const DeviceTerminalProperty *> (p);
return NetlistProperty::equals (p) && m_terminal_ref == pp->m_terminal_ref;
return NetlistProperty::equals (p) && m_terminal_id == pp->m_terminal_id && m_device_id == pp->m_device_id;
}
bool DeviceTerminalProperty::less (const NetlistProperty *p) const
@ -236,7 +172,11 @@ bool DeviceTerminalProperty::less (const NetlistProperty *p) const
return NetlistProperty::less (p);
} else {
const DeviceTerminalProperty *pp = static_cast<const DeviceTerminalProperty *> (p);
return m_terminal_ref < pp->m_terminal_ref;
if (m_terminal_id != pp->m_terminal_id) {
return m_terminal_id < pp->m_terminal_id;
} else {
return m_device_id < pp->m_device_id;
}
}
}
@ -244,17 +184,14 @@ void DeviceTerminalProperty::assign (const NetlistProperty *p)
{
NetlistProperty::assign (p);
const DeviceTerminalProperty *pp = static_cast<const DeviceTerminalProperty *> (p);
m_terminal_ref = pp->m_terminal_ref;
m_terminal_id = pp->m_terminal_id;
m_device_id = pp->m_device_id;
}
std::string DeviceTerminalProperty::to_string () const
{
if (m_terminal_ref.device () && m_terminal_ref.terminal_def ()) {
return "terminal:" + tl::to_word_or_quoted_string (m_terminal_ref.device ()->name ()) + ":" + tl::to_word_or_quoted_string (m_terminal_ref.terminal_def ()->name ());
} else {
return "terminal";
}
return tl::to_string (m_device_id) + ":" + tl::to_string (m_terminal_id);
}
}

View File

@ -151,78 +151,6 @@ public:
}
};
/**
* @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;
private:
std::string m_name;
};
/**
* @brief A reference to a device terminal
*
@ -248,7 +176,7 @@ public:
/**
* @brief Creates a netlist name property with the given name
*/
DeviceTerminalProperty (const db::NetTerminalRef &terminal_ref);
DeviceTerminalProperty (size_t device_id, size_t terminal_id);
/**
* @brief Assignment
@ -258,14 +186,22 @@ public:
/**
* @brief Sets the terminal reference
*/
void set_terminal_ref (const db::NetTerminalRef &terminal_ref);
void set_terminal_ref (size_t device_id, size_t terminal_id);
/**
* @brief Gets the terminal reference
* @brief Gets the terminal ID
*/
const db::NetTerminalRef &terminal_ref () const
size_t terminal_id () const
{
return m_terminal_ref;
return m_terminal_id;
}
/**
* @brief Gets the device ID
*/
size_t device_id () const
{
return m_device_id;
}
/**
@ -297,7 +233,7 @@ public:
virtual std::string to_string () const;
private:
db::NetTerminalRef m_terminal_ref;
size_t m_terminal_id, m_device_id;
};
}

View File

@ -1,122 +0,0 @@
/*
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 ();
}
gsi::Class<db::NetlistProperty> decl_NetlistProperty ("db", "NetlistProperty",
gsi::constructor ("new", &new_property,
"@brief Creates a plain netlist property"
) +
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 terminals. "
"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"
);
// ---------------------------------------------------------------
// db::DeviceTerminalProperty binding
static db::DeviceTerminalProperty *new_devterminal ()
{
return new db::DeviceTerminalProperty ();
}
static db::DeviceTerminalProperty *new_devterminal2 (const db::NetTerminalRef &n)
{
return new db::DeviceTerminalProperty (n);
}
gsi::Class<db::DeviceTerminalProperty> decl_DeviceTerminalProperty (decl_NetlistProperty, "db", "DeviceTerminalProperty",
gsi::constructor ("new", &new_devterminal,
"@brief Creates a new device terminal property"
) +
gsi::constructor ("new", &new_devterminal2, gsi::arg ("terminal_ref"),
"@brief Creates a new device terminal property with the given terminal reference"
) +
gsi::method ("terminal_ref=", &db::DeviceTerminalProperty::set_terminal_ref, gsi::arg ("p"),
"@brief Sets the terminal reference\n"
) +
gsi::method ("terminal_ref", &db::DeviceTerminalProperty::terminal_ref,
"@brief Gets the terminal reference\n"
),
"@brief A device terminal reference property.\n"
"\n"
"The netlist property annotates a shape or other object with a reference to a device terminal."
"\n\n"
"This class was introduced in version 0.26.\n"
);
}

View File

@ -370,9 +370,6 @@ public:
const local_cluster_type &lc = clusters.cluster_by_id (*c);
for (local_cluster_type::attr_iterator a = lc.begin_attr (); a != lc.end_attr (); ++a) {
// @@@ TODO: needs refactoring!!!
// -> use two distinct and reserved property name ID's for names (=string) and device terminal refs (=single number) instead
// of the scary DeviceTerminalProperty (pointer!!!)
const db::PropertiesRepository::properties_set &ps = layout->properties_repository ().properties (*a);
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
@ -381,11 +378,10 @@ public:
if (j->second.is_user<db::NetlistProperty> ()) {
const db::NetlistProperty *np = &j->second.to_user<db::NetlistProperty> ();
const db::DeviceTerminalProperty *tp = dynamic_cast<const db::DeviceTerminalProperty *> (np);
const db::NetNameProperty *nnp = dynamic_cast<const db::NetNameProperty *> (np);
if (tp) {
const_cast<db::Device *> (tp->terminal_ref ().device ())->connect_terminal (tp->terminal_ref ().terminal_id (), net);
} else if (nnp) {
net->set_name (nnp->name ());
db::Device *device = circuit->device_by_id (tp->device_id ());
tl_assert (device != 0);
device->connect_terminal (tp->terminal_id (), net);
}
}

View File

@ -28,58 +28,36 @@
#include <memory>
TEST(1_NameBasic)
TEST(1_TerminalRefBasic)
{
db::NetNameProperty name;
EXPECT_EQ (name.to_string (), "name:''");
db::DeviceTerminalProperty dp (42, 17);
EXPECT_EQ (dp.to_string (), "42:17");
EXPECT_EQ (dp.device_id () == 42, true);
EXPECT_EQ (dp.terminal_id () == 17, true);
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\"'");
}
TEST(2_TerminalRefBasic)
{
db::DeviceClass dc;
dc.add_terminal_definition (db::DeviceTerminalDefinition ("A", "Terminal A"));
dc.add_terminal_definition (db::DeviceTerminalDefinition ("B", "Terminal B"));
db::Device d (&dc, "D");
db::DeviceTerminalProperty dp (db::NetTerminalRef (&d, 1));
EXPECT_EQ (dp.to_string (), "terminal:D:B");
dp.set_terminal_ref (db::NetTerminalRef (&d, 0));
EXPECT_EQ (dp.to_string (), "terminal:D:A");
EXPECT_EQ (dp.terminal_ref () == db::NetTerminalRef (&d, 0), true);
dp.set_terminal_ref (2, 1);
EXPECT_EQ (dp.to_string (), "2:1");
EXPECT_EQ (dp.device_id () == 2, true);
EXPECT_EQ (dp.terminal_id () == 1, true);
db::DeviceTerminalProperty dp2 = dp;
EXPECT_EQ (dp2.to_string (), "terminal:D:A");
EXPECT_EQ (dp2.to_string (), "2:1");
}
TEST(3_Variants)
TEST(2_Variants)
{
std::auto_ptr<db::NetNameProperty> nn (new db::NetNameProperty ());
nn->set_name ("net42");
std::auto_ptr<db::DeviceTerminalProperty> dp (new db::DeviceTerminalProperty ());
dp->set_terminal_ref (42, 17);
tl::Variant v (nn.release (), db::NetlistProperty::variant_class (), true);
tl::Variant v (dp.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");
EXPECT_EQ (dynamic_cast<db::DeviceTerminalProperty &>(v.to_user<db::NetlistProperty> ()).to_string (), "42:17");
EXPECT_EQ (v.to_string (), "42:17");
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");
EXPECT_EQ (dynamic_cast<db::DeviceTerminalProperty &>(vv.to_user<db::NetlistProperty> ()).to_string (), "42:17");
}

View File

@ -109,7 +109,6 @@ RUBYTEST (dbLayoutTest, "dbLayoutTest.rb")
RUBYTEST (dbLayoutDiff, "dbLayoutDiff.rb")
RUBYTEST (dbLayoutQuery, "dbLayoutQuery.rb")
RUBYTEST (dbMatrix, "dbMatrix.rb")
RUBYTEST (dbNetlistProperty, "dbNetlistProperty.rb")
RUBYTEST (dbNetlist, "dbNetlist.rb")
RUBYTEST (dbPathTest, "dbPathTest.rb")
RUBYTEST (dbPCells, "dbPCells.rb")

View File

@ -1,101 +0,0 @@
# 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, "")
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")
end
def test_3_DeviceTerminal
np = RBA::DeviceTerminalProperty::new
assert_equal(np.is_a?(RBA::DeviceTerminalProperty), true)
assert_equal(np.is_a?(RBA::DeviceTerminalProperty), true)
assert_equal(np.to_s, "terminal")
dc = RBA::GenericDeviceClass::new
dp = RBA::DeviceTerminalDefinition::new
dp.name = "A"
dc.add_terminal(dp)
dp.name = "B"
dc.add_terminal(dp)
c = RBA::Circuit::new
d = c.create_device(dc, "D")
n = c.create_net("NET")
d.connect_terminal(0, n)
# there is no other way to produce a NetTerminalRef object yet
n.each_terminal { |p| np.terminal_ref = p }
assert_equal(np.to_s, "terminal:D:A")
assert_equal(np.terminal_ref.device.name, "D")
end
def test_4_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")