Convenience methods Shape#properties, Layout#properties, Cell#properties, Instance#properties

This commit is contained in:
Matthias Koefferlein 2024-07-24 22:29:09 +02:00
parent 6baabc30bb
commit 4cd8772e70
6 changed files with 131 additions and 4 deletions

View File

@ -1104,14 +1104,14 @@ static void set_cell_property (db::Cell *c, const tl::Variant &key, const tl::Va
c->prop_id (layout->properties_repository ().properties_id (props));
}
static tl::Variant get_cell_property (db::Cell *c, const tl::Variant &key)
static tl::Variant get_cell_property (const db::Cell *c, const tl::Variant &key)
{
db::properties_id_type id = c->prop_id ();
if (id == 0) {
return tl::Variant ();
}
db::Layout *layout = c->layout ();
const db::Layout *layout = c->layout ();
if (! layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot retrieve properties")));
}
@ -1130,6 +1130,26 @@ static tl::Variant get_cell_property (db::Cell *c, const tl::Variant &key)
}
}
static tl::Variant get_cell_properties (const db::Cell *c)
{
db::properties_id_type id = c->prop_id ();
if (id == 0) {
return tl::Variant::empty_array ();
}
const db::Layout *layout = c->layout ();
if (! layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot retrieve properties")));
}
tl::Variant res = tl::Variant::empty_array ();
const db::PropertiesRepository::properties_set &props = layout->properties_repository ().properties (id);
for (auto i = props.begin (); i != props.end (); ++i) {
res.insert (layout->properties_repository ().prop_name (i->first), i->second);
}
return res;
}
static bool is_pcell_variant (const db::Cell *cell)
{
tl_assert (cell->layout () != 0);
@ -1841,10 +1861,16 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"@brief Gets the user property with the given key\n"
"This method is a convenience method that gets the property with the given key. "
"If no property with that key exists, it will return nil. Using that method is more "
"convenient than using the layout object and the properties ID to retrieve the property value. "
"convenient than using the layout object and the properties ID to retrieve the property value.\n"
"\n"
"This method has been introduced in version 0.23."
) +
gsi::method_ext ("properties", &get_cell_properties,
"@brief Gets the user properties as a hash\n"
"This method is a convenience method that gets all user properties as a single hash.\n"
"\n"
"This method has been introduced in version 0.29.5."
) +
gsi::method_ext ("add_meta_info", &cell_add_meta_info, gsi::arg ("info"),
"@brief Adds meta information to the cell\n"
"See \\LayoutMetaInfo for details about cells and meta information.\n"
@ -3539,6 +3565,26 @@ static tl::Variant get_property (const db::Instance *i, const tl::Variant &key)
}
}
static tl::Variant get_properties (const db::Instance *i)
{
db::properties_id_type id = i->prop_id ();
if (id == 0) {
return tl::Variant::empty_array ();
}
const db::Layout *layout = layout_ptr_const (i);
if (! layout) {
throw tl::Exception (tl::to_string (tr ("Instance does not reside inside a layout - cannot retrieve properties")));
}
tl::Variant res = tl::Variant::empty_array ();
const db::PropertiesRepository::properties_set &props = layout->properties_repository ().properties (id);
for (auto i = props.begin (); i != props.end (); ++i) {
res.insert (layout->properties_repository ().prop_name (i->first), i->second);
}
return res;
}
static bool inst_is_valid (const db::Instance *inst)
{
return inst->instances () && inst->instances ()->is_valid (*inst);
@ -4011,6 +4057,12 @@ Class<db::Instance> decl_Instance ("db", "Instance",
"\n"
"This method has been introduced in version 0.22."
) +
gsi::method_ext ("properties", &get_properties,
"@brief Gets the user properties as a hash\n"
"This method is a convenience method that gets all user properties as a single hash.\n"
"\n"
"This method has been introduced in version 0.29.5."
) +
method_ext ("[]", &inst_index, gsi::arg ("key"),
"@brief Gets the user property with the given key or, if available, the PCell parameter with the name given by the key\n"
"Getting the PCell parameter has priority over the user property."

View File

@ -344,7 +344,7 @@ static void set_layout_property (db::Layout *l, const tl::Variant &key, const tl
l->prop_id (l->properties_repository ().properties_id (props));
}
static tl::Variant get_layout_property (db::Layout *l, const tl::Variant &key)
static tl::Variant get_layout_property (const db::Layout *l, const tl::Variant &key)
{
// TODO: check if is editable
@ -367,6 +367,21 @@ static tl::Variant get_layout_property (db::Layout *l, const tl::Variant &key)
}
}
static tl::Variant get_layout_properties (const db::Layout *layout)
{
db::properties_id_type id = layout->prop_id ();
if (id == 0) {
return tl::Variant::empty_array ();
}
tl::Variant res = tl::Variant::empty_array ();
const db::PropertiesRepository::properties_set &props = layout->properties_repository ().properties (id);
for (auto i = props.begin (); i != props.end (); ++i) {
res.insert (layout->properties_repository ().prop_name (i->first), i->second);
}
return res;
}
static db::cell_index_type cell_by_name (db::Layout *l, const char *name)
{
std::pair<bool, db::cell_index_type> c = l->cell_by_name (name);
@ -1265,6 +1280,12 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"This method has been introduced in version 0.24."
) +
gsi::method_ext ("properties", &get_layout_properties,
"@brief Gets the user properties as a hash\n"
"This method is a convenience method that gets all user properties as a single hash.\n"
"\n"
"This method has been introduced in version 0.29.5."
) +
gsi::method_ext ("properties_id", &properties_id, gsi::arg ("properties"),
"@brief Gets the properties ID for a given properties set\n"
"\n"

View File

@ -1004,6 +1004,26 @@ static tl::Variant get_property (const db::Shape *s, const tl::Variant &key)
}
}
static tl::Variant get_properties (const db::Shape *s)
{
db::properties_id_type id = s->prop_id ();
if (id == 0) {
return tl::Variant::empty_array ();
}
const db::Layout *layout = layout_ptr_const (s);
if (! layout) {
throw tl::Exception (tl::to_string (tr ("Shape does not reside inside a layout - cannot retrieve properties")));
}
tl::Variant res = tl::Variant::empty_array ();
const db::PropertiesRepository::properties_set &props = layout->properties_repository ().properties (id);
for (auto i = props.begin (); i != props.end (); ++i) {
res.insert (layout->properties_repository ().prop_name (i->first), i->second);
}
return res;
}
namespace
{
@ -1354,6 +1374,12 @@ Class<db::Shape> decl_Shape ("db", "Shape",
"\n"
"This method has been introduced in version 0.22."
) +
gsi::method_ext ("properties", &get_properties,
"@brief Gets the user properties\n"
"This method is a convenience method that gets the properties of the shape as a hash. "
"\n"
"This method has been introduced in version 0.29.5."
) +
gsi::iterator ("each_point", &db::Shape::begin_point, &db::Shape::end_point,
"@brief Iterates over all points of the object\n"
"\n"

View File

@ -1334,6 +1334,7 @@ class DBLayoutTests1_TestClass < TestBase
i0 = nil
c0c.each_inst { |i| i.cell_index == l.cell("c1$1").cell_index && i0 = i }
assert_equal(i0.property("p"), 18)
assert_equal(i0.properties, {"p" => 18})
assert_equal(l.cell("c1$1").begin_shapes_rec(0).shape.property("p"), 17)
assert_equal(collect(c0c.begin_shapes_rec(0), l), "[c0$1](0,100;1000,1200)/[c2$1](100,0;1100,1100)/[c3$1](1200,0;2200,1100)/[c3$1](-1200,0;-100,1000)/[c1$1](0,100;1000,1200)")
@ -1379,6 +1380,7 @@ class DBLayoutTests1_TestClass < TestBase
tt = RBA::Trans.new
i0 = c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
assert_equal(i0.properties, {})
i0.set_property("p", 18)
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1)))

View File

@ -674,6 +674,7 @@ class DBLayoutTests2_TestClass < TestBase
lindex = ly.insert_layer( linfo )
c1 = ly.cell( ci1 )
assert_equal( c1.properties, {} )
c2 = ly.cell( ci2 )
tr = RBA::Trans::new
inst = c2.insert( RBA::CellInstArray::new( c1.cell_index, tr ) )
@ -701,6 +702,7 @@ class DBLayoutTests2_TestClass < TestBase
c1.prop_id = pid
assert_equal( c1.prop_id, pid )
assert_equal( c1.property( 17 ).inspect, "\"a\"" )
assert_equal( c1.properties, { 17 => "a", "b" => [1, 5, 7] } )
c1.set_property( 5, 23 )
c1.delete_property( 17 )
assert_equal( c1.property( 17 ).inspect, "nil" )
@ -1027,6 +1029,7 @@ class DBLayoutTests2_TestClass < TestBase
def test_11
ly = RBA::Layout::new
assert_equal(ly.properties, {})
assert_equal(ly.prop_id, 0)
ly.prop_id = 1
@ -1037,6 +1040,7 @@ class DBLayoutTests2_TestClass < TestBase
ly.set_property("x", 1)
assert_equal(ly.prop_id, 1)
assert_equal(ly.property("x"), 1)
assert_equal(ly.properties, {"x" => 1})
ly.set_property("x", 17)
assert_equal(ly.prop_id, 2)
assert_equal(ly.property("x"), 17)

View File

@ -1656,6 +1656,28 @@ class DBShapes_TestClass < TestBase
end
# Shape objects and properties
def test_13
ly = RBA::Layout::new
l1 = ly.layer(1, 0)
tc = ly.create_cell("TOP")
sh = tc.shapes(l1).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(sh.property("k").inspect, "nil")
assert_equal(sh.properties.inspect, "{}")
sh.set_property("k", 17)
assert_equal(sh.property("k").inspect, "17")
assert_equal(sh.property("u").inspect, "nil")
assert_equal(sh.properties.inspect, "{\"k\"=>17}")
sh.set_property("u", "42")
assert_equal(sh.properties.inspect, "{\"k\"=>17, \"u\"=>\"42\"}")
end
end
load("test_epilogue.rb")