From d9e0d107b1312e81464f56466bc89f31bbdad0dc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 21 Apr 2023 23:33:42 +0200 Subject: [PATCH] Bug fixes, RBA tests for meta info --- src/db/db/dbLayout.cc | 23 ++++++++-- src/db/db/dbLayout.h | 26 ++++++++++++ src/db/db/gsiDeclDbCell.cc | 13 +++--- src/db/db/gsiDeclDbLayout.cc | 14 ++++--- src/db/db/gsiDeclDbMetaInfo.cc | 20 ++++++++- testdata/ruby/dbLayoutTests2.rb | 74 ++++++++++++++++++++++++++++----- 6 files changed, 144 insertions(+), 26 deletions(-) diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index a03a874a7..30b732167 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -1799,7 +1799,7 @@ Layout::meta_info_iterator Layout::begin_meta (db::cell_index_type ci) const { auto m = m_meta_info_by_cell.find (ci); - if (m != m_meta_info_by_cell.find (ci)) { + if (m != m_meta_info_by_cell.end ()) { return m->second.begin (); } else { return s_empty_meta.begin (); @@ -1810,7 +1810,7 @@ Layout::meta_info_iterator Layout::end_meta (db::cell_index_type ci) const { auto m = m_meta_info_by_cell.find (ci); - if (m != m_meta_info_by_cell.find (ci)) { + if (m != m_meta_info_by_cell.end ()) { return m->second.end (); } else { return s_empty_meta.end (); @@ -1871,6 +1871,12 @@ Layout::meta_info (meta_info_name_id_type name_id) const return n != m_meta_info.end () ? n->second : null_value; } +bool +Layout::has_meta_info (meta_info_name_id_type name_id) const +{ + return m_meta_info.find (name_id) != m_meta_info.end (); +} + void Layout::clear_meta (db::cell_index_type ci) { @@ -1907,7 +1913,18 @@ Layout::meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) const return null_value; } -void +bool +Layout::has_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) const +{ + auto c = m_meta_info_by_cell.find (ci); + if (c != m_meta_info_by_cell.end ()) { + return c->second.find (name_id) != c->second.end (); + } else { + return false; + } +} + +void Layout::swap_layers (unsigned int a, unsigned int b) { tl_assert (m_layers.layer_state (a) != LayoutLayers::Free); diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index c82e5cb14..73918fb5f 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -1932,6 +1932,19 @@ public: */ const MetaInfo &meta_info (meta_info_name_id_type name_id) const; + /** + * @brief Gets a value indicating whether a meta info with the given name is present + */ + bool has_meta_info (const std::string &name) const + { + return has_meta_info (meta_info_name_id (name)); + } + + /** + * @brief Gets a value indicating whether a meta info with the given name is present + */ + bool has_meta_info (meta_info_name_id_type name_id) const; + /** * @brief Clears the meta information for a specific cell */ @@ -1954,6 +1967,19 @@ public: */ void add_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id, const MetaInfo &i); + /** + * @brief Gets a value indicating whether a meta info with the given name is present for the given cell + */ + bool has_meta_info (db::cell_index_type ci, const std::string &name) const + { + return has_meta_info (ci, meta_info_name_id (name)); + } + + /** + * @brief Gets a value indicating whether a meta info with the given name is present for the given cell + */ + bool has_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) const; + /** * @brief Removes the meta information object with the given name from the given cell * The method will do nothing if no object with that name exists. diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index ecff73f45..936fceeff 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1014,14 +1014,15 @@ static const tl::Variant &cell_meta_info_value (db::Cell *cell, const std::strin } } -static MetaInfo cell_meta_info (db::Cell *cell, const std::string &name) +static MetaInfo *cell_meta_info (db::Cell *cell, const std::string &name) { if (! cell->layout ()) { - static MetaInfo null_value; - return null_value; - } else { + return 0; + } else if (cell->layout ()->has_meta_info (cell->cell_index (), name)) { const db::MetaInfo &value = cell->layout ()->meta_info (cell->cell_index (), name); - return MetaInfo (name, value); + return new MetaInfo (name, value); + } else { + return 0; } } @@ -1857,7 +1858,7 @@ Class decl_Cell ("db", "Cell", "\n" "This method has been introduced in version 0.28.8." ) + - gsi::method_ext ("meta_info", &cell_meta_info, gsi::arg ("name"), + gsi::factory_ext ("meta_info", &cell_meta_info, gsi::arg ("name"), "@brief Gets the meta information for a given name\n" "See \\LayoutMetaInfo for details about cells and meta information.\n" "\n" diff --git a/src/db/db/gsiDeclDbLayout.cc b/src/db/db/gsiDeclDbLayout.cc index c3734d715..da083b9ee 100644 --- a/src/db/db/gsiDeclDbLayout.cc +++ b/src/db/db/gsiDeclDbLayout.cc @@ -908,10 +908,14 @@ static void layout_add_meta_info (db::Layout *layout, const MetaInfo &mi) layout->add_meta_info (mi.name, db::MetaInfo (mi.description, mi.value)); } -static MetaInfo layout_get_meta_info (db::Layout *layout, const std::string &name) +static MetaInfo *layout_get_meta_info (db::Layout *layout, const std::string &name) { - const db::MetaInfo &value = layout->meta_info (name); - return MetaInfo (name, value); + if (layout->has_meta_info (name)) { + const db::MetaInfo &value = layout->meta_info (name); + return new MetaInfo (name, value); + } else { + return 0; + } } static const tl::Variant &layout_get_meta_info_value (db::Layout *layout, const std::string &name) @@ -1073,11 +1077,11 @@ Class decl_Layout ("db", "Layout", "\n" "This method has been introduced in version 0.25. Starting with version 0.28.8, the value is of variant type instead of string only.\n" ) + - gsi::method_ext ("meta_info", &layout_get_meta_info, gsi::arg ("name"), + gsi::factory_ext ("meta_info", &layout_get_meta_info, gsi::arg ("name"), "@brief Gets the meta information for a given name\n" "See \\LayoutMetaInfo for details about layouts and meta information.\n" "\n" - "If no meta information with the given name exists, a default object with empty fields will be returned.\n" + "If no meta information with the given name exists, nil is returned.\n" "\n" "This method has been introduced in version 0.28.8.\n" ) + diff --git a/src/db/db/gsiDeclDbMetaInfo.cc b/src/db/db/gsiDeclDbMetaInfo.cc index d4161b0e6..9835d86c4 100644 --- a/src/db/db/gsiDeclDbMetaInfo.cc +++ b/src/db/db/gsiDeclDbMetaInfo.cc @@ -27,7 +27,7 @@ namespace gsi { -static MetaInfo *layout_meta_info_ctor (const std::string &name, const std::string &value, const std::string &description, bool persisted) +static MetaInfo *layout_meta_info_ctor (const std::string &name, const tl::Variant &value, const std::string &description, bool persisted) { return new MetaInfo (name, description, value, persisted); } @@ -101,7 +101,7 @@ Class decl_LayoutMetaInfo ("db", "LayoutMetaInfo", gsi::method_ext ("description=", &layout_meta_set_description, "@brief Sets the description of the layout meta info object\n" ) + - gsi::method_ext ("persisted", &layout_meta_get_persisted, + gsi::method_ext ("is_persisted?", &layout_meta_get_persisted, "@brief Gets a value indicating whether the meta information will be persisted\n" "This predicate was introduced in version 0.28.8.\n" ) + @@ -118,6 +118,22 @@ Class decl_LayoutMetaInfo ("db", "LayoutMetaInfo", "Meta information is identified by a unique name and carries a string value plus an optional description string. " "The description string is for information only and is not evaluated by code.\n" "\n" + "Meta information can be attached to the layout object and to cells. It is similar to " + "user properties. The differences are:\n" + "\n" + "@ul\n" + "@li Meta information is stored differently in GDS and OASIS files using the context information added " + " by KLayout to annotated PCell or library cells too. Hence meta information does not pollute " + " the standard user properties space. @/li\n" + "@li The value of meta information can be complex serializable types such as lists, hashes and elementary " + " objects such as \\Box or \\DBox. Scalar types include floats and booleans. @/li\n" + "@li Meta information keys are strings and are supported also for GDS which only accepts integer number " + " keys for user properties. @/li\n" + "@/ul\n" + "\n" + "Note that only meta information marked with \\is_persisted? == true are stored in GDS or OASIS files. " + "This is not the default setting, so you need to explicitly set that flag.\n" + "\n" "See also \\Layout#each_meta_info, \\Layout#meta_info_value, \\Layout#meta_info and \\Layout#remove_meta_info as " "well as the corresponding \\Cell methods.\n" "\n" diff --git a/testdata/ruby/dbLayoutTests2.rb b/testdata/ruby/dbLayoutTests2.rb index e204b2e3c..32b291f2a 100644 --- a/testdata/ruby/dbLayoutTests2.rb +++ b/testdata/ruby/dbLayoutTests2.rb @@ -1044,36 +1044,39 @@ class DBLayoutTests2_TestClass < TestBase end # Meta information - def test_12 + def test_12a mi = RBA::LayoutMetaInfo::new("myinfo", "a") assert_equal(mi.name, "myinfo") assert_equal(mi.description, "") assert_equal(mi.value, "a") + assert_equal(mi.is_persisted?, false) mi.name = "x" mi.description = "y" mi.value = "z" + mi.persisted = true assert_equal(mi.name, "x") assert_equal(mi.description, "y") assert_equal(mi.value, "z") + assert_equal(mi.is_persisted?, true) ly = RBA::Layout::new ly.add_meta_info(RBA::LayoutMetaInfo::new("myinfo", "a")) - ly.add_meta_info(RBA::LayoutMetaInfo::new("another", "42", "description")) + ly.add_meta_info(RBA::LayoutMetaInfo::new("another", 42, "description")) assert_equal(ly.meta_info_value("myinfo"), "a") - assert_equal(ly.meta_info_value("doesnotexist"), "") - assert_equal(ly.meta_info_value("another"), "42") + assert_equal(ly.meta_info_value("doesnotexist"), nil) + assert_equal(ly.meta_info_value("another"), 42) a = [] ly.each_meta_info { |mi| a << mi.name } assert_equal(a.join(","), "myinfo,another") a = [] - ly.each_meta_info { |mi| a << mi.value } + ly.each_meta_info { |mi| a << mi.value.to_s } assert_equal(a.join(","), "a,42") a = [] ly.each_meta_info { |mi| a << mi.description } @@ -1081,13 +1084,64 @@ class DBLayoutTests2_TestClass < TestBase ly.add_meta_info(RBA::LayoutMetaInfo::new("myinfo", "b")) assert_equal(ly.meta_info_value("myinfo"), "b") - assert_equal(ly.meta_info_value("doesnotexist"), "") - assert_equal(ly.meta_info_value("another"), "42") + assert_equal(ly.meta_info_value("doesnotexist"), nil) + assert_equal(ly.meta_info_value("another"), 42) + + ly.remove_meta_info("doesnotexist") # should not fail ly.remove_meta_info("myinfo") - assert_equal(ly.meta_info_value("myinfo"), "") - assert_equal(ly.meta_info_value("doesnotexist"), "") - assert_equal(ly.meta_info_value("another"), "42") + assert_equal(ly.meta_info_value("myinfo"), nil) + assert_equal(ly.meta_info_value("doesnotexist"), nil) + assert_equal(ly.meta_info_value("another"), 42) + + assert_equal(ly.meta_info("doesnotexist"), nil) + assert_equal(ly.meta_info("another").value, 42) + assert_equal(ly.meta_info("another").description, "description") + + ly.clear_meta_info + assert_equal(ly.meta_info_value("another"), nil) + assert_equal(ly.meta_info("another"), nil) + + # cellwise + + c1 = ly.create_cell("X") + c2 = ly.create_cell("U") + + c1.add_meta_info(RBA::LayoutMetaInfo::new("a", true)) + c1.add_meta_info(RBA::LayoutMetaInfo::new("b", [ 1, 17, 42 ])) + + assert_equal(c2.meta_info("a"), nil) + assert_equal(c2.meta_info_value("a"), nil) + + a = [] + c2.each_meta_info { |mi| a << mi.value.to_s } + assert_equal(a.join(","), "") + + assert_equal(c1.meta_info("a").value, true) + assert_equal(c1.meta_info("b").value, [ 1, 17, 42 ]) + assert_equal(c1.meta_info_value("b"), [ 1, 17, 42 ]) + + a = [] + c1.each_meta_info { |mi| a << mi.value.to_s } + assert_equal(a.join(","), "true,[1, 17, 42]") + + c1.remove_meta_info("doesnotexist") # should not fail + + a = [] + c1.each_meta_info { |mi| a << mi.value.to_s } + assert_equal(a.join(","), "true,[1, 17, 42]") + + c1.remove_meta_info("b") + + a = [] + c1.each_meta_info { |mi| a << mi.value.to_s } + assert_equal(a.join(","), "true") + + c1.clear_meta_info + + a = [] + c1.each_meta_info { |mi| a << mi.value.to_s } + assert_equal(a.join(","), "") end