From 6e3eb568c342b81c386dfa03294ee3d1c5ff69ce Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 28 Apr 2024 15:30:29 +0200 Subject: [PATCH] Implementing variant reporting Instead of reporting working layout cell names, the original cell names plus a variant indicator is reported. Also, the variant information from the RDB is filled now. Also, the marker browser now shows the qname of the cells instead of the name alone. --- src/db/db/dbCellVariants.cc | 20 ++++++++---- src/db/db/dbDeepShapeStore.cc | 35 +++++++++++++++++++-- src/db/db/dbHierarchyBuilder.cc | 42 ++++++++++++++++++++++++- src/db/db/dbHierarchyBuilder.h | 18 ++++++++++- src/db/db/dbLayout.cc | 3 ++ src/db/db/dbLayout.h | 20 ++++++++++++ src/layui/layui/rdbMarkerBrowserPage.cc | 4 +-- src/rdb/rdb/rdbUtils.cc | 22 +++++++++++-- 8 files changed, 149 insertions(+), 15 deletions(-) diff --git a/src/db/db/dbCellVariants.cc b/src/db/db/dbCellVariants.cc index d1135c30a..af549ad8a 100644 --- a/src/db/db/dbCellVariants.cc +++ b/src/db/db/dbCellVariants.cc @@ -288,6 +288,7 @@ VariantsCollectorBase::separate_variants (std::mapempty ()); for (db::Layout::bottom_up_const_iterator c = mp_layout->begin_bottom_up (); c != mp_layout->end_bottom_up (); ++c) { @@ -311,6 +312,9 @@ VariantsCollectorBase::separate_variants (std::mapsecond.begin (); v != vc->second.end (); ++v, ++index) { @@ -333,6 +337,8 @@ VariantsCollectorBase::separate_variants (std::mapfirst.is_unity ()) { - std::set &tv = m_variants [*c]; - tv.clear (); - tv.insert (vt.begin ()->first); - } else { - m_variants.erase (*c); + if (original_cell_is_variant) { + if (! original_cell_variant.is_unity ()) { + std::set &tv = m_variants [*c]; + tv.clear (); + tv.insert (original_cell_variant); + } else { + m_variants.erase (*c); + } } } else { diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 02a33fcaa..db052be3b 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -298,28 +298,57 @@ struct DeepShapeStore::LayoutHolder { public: VariantsCreatedListener (DeepShapeStore::LayoutHolder *lh, db::Layout *ly) - : mp_lh (lh) + : mp_lh (lh), m_dbu (ly->dbu ()) { ly->variants_created_event.add (this, &VariantsCreatedListener::variants_created); } private: + std::string var_desc (const db::ICplxTrans &t) + { + std::string s; + if (t.is_mirror ()) { + s += "m"; + s += tl::to_string (t.angle () * 0.5); + } else { + s += "r"; + s += tl::to_string (t.angle ()); + } + if (t.is_mag ()) { + s += tl::sprintf ("*%.9g", t.mag ()); + } + if (t.disp () != db::Vector ()) { + s += tl::sprintf ("(%.12g,%.12g)", t.disp ().x () * m_dbu, t.disp ().y () * m_dbu); + } + return s; + } + void variants_created (const std::map > *var_map) { for (std::map >::const_iterator i = var_map->begin (); i != var_map->end (); ++i) { for (std::map::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { - mp_lh->builder.register_variant (i->first, j->second); + if (i->first != j->second) { + mp_lh->builder.register_variant (i->first, j->second, var_desc (j->first)); + } + } + // NOTE: variant conversion events are registered after variant formation events, so we can + // base the formed variants (first pass) on the originals. + for (std::map::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { + if (i->first == j->second) { + mp_lh->builder.register_variant (i->first, j->second, var_desc (j->first)); + } } } } DeepShapeStore::LayoutHolder *mp_lh; + double m_dbu; }; LayoutHolder (const db::ICplxTrans &trans) : refs (0), layout (false), builder (&layout, trans), variants_created (this, &layout) { - // .. nothing yet .. + layout.set_hierarchy_builder (&builder); } void add_layer_ref (unsigned int layer) diff --git a/src/db/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc index bbfd1d68e..f8476730d 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -182,14 +182,24 @@ HierarchyBuilder::reset () m_cells_to_be_filled.clear (); m_cell_map.clear (); + m_variants_of_sources_map.clear (); m_cells_seen.clear (); m_cell_stack.clear (); m_cm_entry = null_iterator; m_cm_new_entry = false; } +const std::pair & +HierarchyBuilder::variant_of_source (db::cell_index_type target) const +{ + static std::pair def (std::numeric_limits::max (), std::string ()); + + auto vs = m_variants_of_sources_map.find (target); + return vs != m_variants_of_sources_map.end () ? vs->second : def; +} + void -HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var) +HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var, const std::string &description) { // non_var (despite its name) may be a variant created previously. variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (non_var); @@ -199,11 +209,23 @@ HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_ m_original_targets_to_variants_map [non_var].push_back (var); m_variants_to_original_target_map.insert (std::make_pair (var, non_var)); + + auto vs = m_variants_of_sources_map.find (non_var); + if (vs != m_variants_of_sources_map.end ()) { + std::string new_description = vs->second.second; + if (! new_description.empty ()) { + new_description += ";"; + } + new_description += description; + m_variants_of_sources_map [var] = std::make_pair (vs->second.first, new_description); + } } void HierarchyBuilder::unregister_variant (db::cell_index_type var) { + m_variants_of_sources_map.erase (var); + variant_to_original_target_map_type::iterator v = m_variants_to_original_target_map.find (var); if (v == m_variants_to_original_target_map.end ()) { return; @@ -257,6 +279,7 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter) if (m_cm_entry == m_cell_map.end ()) { db::cell_index_type new_top_index = mp_target->add_cell (iter->layout ()->cell_name (key.original_cell)); m_cm_entry = m_cell_map.insert (std::make_pair (key, new_top_index)).first; + m_variants_of_sources_map.insert (std::make_pair (new_top_index, std::make_pair (key.original_cell, std::string ()))); } db::Cell &new_top = mp_target->cell (m_cm_entry->second); @@ -324,17 +347,34 @@ HierarchyBuilder::make_cell_variant (const HierarchyBuilder::CellMapKey &key, co if (m_cm_entry == m_cell_map.end ()) { std::string cn = cell_name; + std::string description; if (! key.clip_region.empty ()) { cn += "$CLIP_VAR"; + description += "CLIP"; + } if (key.inactive) { cn += "$DIS"; + if (! description.empty ()) { + description += "/"; + } + description += "DISABLED"; } + new_cell = mp_target->add_cell (cn.c_str ()); + + std::string new_name = mp_target->cell_name (new_cell); + if (new_name.size () > cn.size ()) { + // use cell name extension to uniquify the description + description += new_name.c_str () + cn.size (); + } + m_cm_entry = m_cell_map.insert (std::make_pair (key, new_cell)).first; m_cm_new_entry = true; m_cells_to_be_filled.insert (new_cell); + m_variants_of_sources_map.insert (std::make_pair (new_cell, std::make_pair (key.original_cell, description))); + } else { new_cell = m_cm_entry->second; } diff --git a/src/db/db/dbHierarchyBuilder.h b/src/db/db/dbHierarchyBuilder.h index 70c76b2fe..4cd0caf65 100644 --- a/src/db/db/dbHierarchyBuilder.h +++ b/src/db/db/dbHierarchyBuilder.h @@ -389,7 +389,7 @@ public: * The first cell is either the original, non-variant target cell or itself a variant. * The second cell will be registered as a variant of the first one. */ - void register_variant (db::cell_index_type non_var, db::cell_index_type var); + void register_variant (db::cell_index_type non_var, db::cell_index_type var, const std::string &description); /** * @brief Unregisters a cell as a variant @@ -404,8 +404,23 @@ public: return m_variants_to_original_target_map.find (ci) != m_variants_to_original_target_map.end (); } + /** + * @brief Gets the information about the target/source + variant relationship + * + * For a target cell, returns a pointer to a pair with the cell index of the source cell and + * a string describing the variant this cell forms of the source cell. + * + * The description string is empty if the cell is not a variant. + */ + const std::pair &variant_of_source (db::cell_index_type target) const; + /** * @brief Gets the original target for a variant cell + * + * The original cell is the first-generation target-space cell that variants have been created for. + * This still can mean that the original cell is a clip variant of a source cell. + * + * Target-to-source variants can be derived with "variant_of_source". */ db::cell_index_type original_target_for_variant (db::cell_index_type ci) const; @@ -419,6 +434,7 @@ private: cell_map_type m_cell_map; original_target_to_variants_map_type m_original_targets_to_variants_map; variant_to_original_target_map_type m_variants_to_original_target_map; + std::map > m_variants_of_sources_map; std::set m_cells_seen; std::set m_cells_to_be_filled; diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index 4e29d27ef..319f10bae 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -439,6 +439,7 @@ LayoutOrCellContextInfo::has_meta_info () const Layout::Layout (db::Manager *manager) : db::Object (manager), mp_library (0), + mp_builder (0), m_cells_size (0), m_invalid (0), m_top_cells (0), @@ -454,6 +455,7 @@ Layout::Layout (db::Manager *manager) Layout::Layout (bool editable, db::Manager *manager) : db::Object (manager), mp_library (0), + mp_builder (0), m_cells_size (0), m_invalid (0), m_top_cells (0), @@ -473,6 +475,7 @@ Layout::Layout (const db::Layout &layout) tl::Object (), tl::UniqueId (), mp_library (0), + mp_builder (0), m_cells_size (0), m_invalid (0), m_top_cells (0), diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index 59a4ad19f..4ab44a12e 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -72,6 +72,7 @@ class Technology; class CellMapping; class LayerMapping; class VariantsCollectorBase; +class HierarchyBuilder; template class generic_repository; typedef generic_repository GenericRepository; @@ -2113,6 +2114,24 @@ public: */ const MetaInfo &meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) const; + /** + * @brief Sets the hierarchy builder reference + * Used internally + */ + void set_hierarchy_builder (db::HierarchyBuilder *builder) + { + mp_builder = builder; + } + + /** + * @brief Gets the hierarchy builder + * Used internally + */ + db::HierarchyBuilder *builder () const + { + return mp_builder; + } + /** * @brief This event is triggered when the technology changes */ @@ -2138,6 +2157,7 @@ protected: private: db::Library *mp_library; + db::HierarchyBuilder *mp_builder; cell_list m_cells; size_t m_cells_size; cell_ptr_vector m_cell_ptrs; diff --git a/src/layui/layui/rdbMarkerBrowserPage.cc b/src/layui/layui/rdbMarkerBrowserPage.cc index e6c87b117..380e327e7 100644 --- a/src/layui/layui/rdbMarkerBrowserPage.cc +++ b/src/layui/layui/rdbMarkerBrowserPage.cc @@ -287,7 +287,7 @@ SortByKeyCompareFunc::operator() (MarkerBrowserTreeViewModelCacheEntry *a, Marke const rdb::Cell *ca = mp_rdb->cell_by_id (a->id ()); const rdb::Cell *cb = mp_rdb->cell_by_id (b->id ()); if (ca && cb) { - return m_ascending ? ca->name () < cb->name () : cb->name () < ca->name (); + return m_ascending ? ca->qname () < cb->qname () : cb->qname () < ca->qname (); } const rdb::Category *xa = mp_rdb->category_by_id (a->id ()); @@ -582,7 +582,7 @@ public: if (cell->name ().empty ()) { return QObject::tr ("All Cells"); } else { - return QVariant (QString::fromUtf8 ("[") + tl::to_qstring (cell->name ()) + QString::fromUtf8 ("]")); + return QVariant (QString::fromUtf8 ("[") + tl::to_qstring (cell->qname ()) + QString::fromUtf8 ("]")); } } diff --git a/src/rdb/rdb/rdbUtils.cc b/src/rdb/rdb/rdbUtils.cc index 766d43183..6b17dd753 100644 --- a/src/rdb/rdb/rdbUtils.cc +++ b/src/rdb/rdb/rdbUtils.cc @@ -174,10 +174,28 @@ public: const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci) { tl_assert (layout != 0); + std::string cn = layout->cell_name (ci); - const rdb::Cell *rdb_cell = mp_rdb->cell_by_qname (cn); + std::string layout_cn = cn; + std::string qname = cn; + std::string var; + + // resolve references to original cells in deep mode and determine variant + if (layout->builder ()) { + const db::Layout *source = layout->builder ()->source ().layout (); + if (source) { + const std::pair &vs = layout->builder ()->variant_of_source (ci); + if (! vs.second.empty () && source->is_valid_cell_index (vs.first)) { + var = vs.second; + cn = source->cell_name (vs.first); + qname = cn + ":" + var; + } + } + } + + const rdb::Cell *rdb_cell = mp_rdb->cell_by_qname (qname); if (! rdb_cell) { - return mp_rdb->create_cell (cn); + return mp_rdb->create_cell (cn, var, layout_cn); } else { return rdb_cell; }