From 4c47cfb03a28f4594b353f7b20a99b33ab582853 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 23 Mar 2026 22:49:47 +0100 Subject: [PATCH] WIP: 'sparse_array_limit' on DSS --- src/db/db/dbDeepShapeStore.cc | 18 ++++++++++++++++-- src/db/db/dbDeepShapeStore.h | 22 ++++++++++++++++++++++ src/db/db/dbHierarchyBuilder.cc | 26 +++++++++++++++----------- src/db/db/dbHierarchyBuilder.h | 21 +++++++++++++++++++++ src/db/db/gsiDeclDbDeepShapeStore.cc | 20 ++++++++++++++++++++ 5 files changed, 94 insertions(+), 13 deletions(-) diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 3973d1b6d..5ded121e1 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -571,13 +571,13 @@ static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIter } DeepShapeStore::DeepShapeStore () - : m_keep_layouts (true), m_wants_all_cells (false) + : m_keep_layouts (true), m_wants_all_cells (false), m_sparse_array_limit (-1.0) { ++s_instance_count; } DeepShapeStore::DeepShapeStore (const std::string &topcell_name, double dbu) - : m_keep_layouts (true), m_wants_all_cells (false) + : m_keep_layouts (true), m_wants_all_cells (false), m_sparse_array_limit (-1.0) { ++s_instance_count; @@ -865,6 +865,16 @@ bool DeepShapeStore::wants_all_cells () const return m_wants_all_cells; } +void DeepShapeStore::set_sparse_array_limit (double l) +{ + m_sparse_array_limit = l; +} + +double DeepShapeStore::sparse_array_limit () const +{ + return m_sparse_array_limit; +} + void DeepShapeStore::set_reject_odd_polygons (bool f) { m_state.set_reject_odd_polygons (f); @@ -1030,6 +1040,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator db::HierarchyBuilder &builder = m_layouts[layout_index]->builder; builder.set_wants_all_cells (m_wants_all_cells); + builder.set_sparse_array_limit (m_sparse_array_limit); unsigned int layer_index = init_layer (layout, si); builder.set_target_layer (layer_index); @@ -1064,6 +1075,9 @@ DeepLayer DeepShapeStore::create_custom_layer (const db::RecursiveShapeIterator db::Layout &layout = m_layouts[layout_index]->layout; db::HierarchyBuilder &builder = m_layouts[layout_index]->builder; + builder.set_wants_all_cells (m_wants_all_cells); + builder.set_sparse_array_limit (m_sparse_array_limit); + unsigned int layer_index = init_layer (layout, si); builder.set_target_layer (layer_index); diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index f60a124f7..60233e23a 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -701,6 +701,27 @@ public: */ bool wants_all_cells () const; + /** + * @brief Sets the "sparse array" limit + * + * Sparse arrays are instance arrays whose bounding box is no longer a + * good approximation of the covered area. The "sparse array ratio" is + * the area of the bounding box divided by the area of the bounding box + * of a single instance. + * + * Arrays above this limit will be resolved into single instances. + * + * Setting this value to 0 will resolve all arrays. Setting this + * value to a negative value will never split arrays. The latter + * is the default. + */ + void set_sparse_array_limit (double l); + + /** + * @brief Gets the "sparse array" limit + */ + double sparse_array_limit () const; + /** * @brief Sets a flag indicating whether to reject odd polygons * @@ -858,6 +879,7 @@ private: std::list m_state_stack; bool m_keep_layouts; bool m_wants_all_cells; + double m_sparse_array_limit; tl::Mutex m_lock; struct DeliveryMappingCacheKey diff --git a/src/db/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc index 41ca8685f..d5086951c 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -152,14 +152,14 @@ static std::pair > compute_clip_variant (const db::Box & } HierarchyBuilder::HierarchyBuilder (db::Layout *target, unsigned int target_layer, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe) - : mp_target (target), m_target_layer (target_layer), m_wants_all_cells (false), m_trans (trans) + : mp_target (target), m_target_layer (target_layer), m_wants_all_cells (false), m_trans (trans), m_sparse_array_limit (-1.0) { set_shape_receiver (pipe); reset (); } HierarchyBuilder::HierarchyBuilder (db::Layout *target, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe) - : mp_target (target), m_target_layer (0), m_wants_all_cells (false), m_trans (trans) + : mp_target (target), m_target_layer (0), m_wants_all_cells (false), m_trans (trans), m_sparse_array_limit (-1.0) { set_shape_receiver (pipe); reset (); @@ -397,19 +397,23 @@ HierarchyBuilder::new_inst (const RecursiveShapeIterator *iter, const db::CellIn // for new cells, create this instance if (m_cell_stack.back ().first || m_cm_new_entry) { - // @@@ - // check if the cell array is "sparse" + // check if the cell array is "sparse" according to + // "sparse_array_limit" and resolve into single instances if so bool resolve = false; - if (m_source.layout () && inst.size () > 1) { - db::box_convert bc (*m_source.layout ()); - auto a1 = bc (inst.object ()).area (); - auto aa = inst.bbox (bc).area (); - double area_ratio = 10.0; // @@@ - if (a1 * area_ratio < aa) { + if (m_sparse_array_limit >= 0.0 && inst.size () > 1) { + + if (m_sparse_array_limit == 0.0) { resolve = true; + } else { + db::box_convert bc (*iter->layout ()); + auto a1 = bc (inst.object ()).area (); + auto aa = inst.bbox (bc).area (); + if (a1 * m_sparse_array_limit < aa) { + resolve = true; + } } + } - // @@@ if (resolve) { diff --git a/src/db/db/dbHierarchyBuilder.h b/src/db/db/dbHierarchyBuilder.h index cf08453a5..80c67c3cd 100644 --- a/src/db/db/dbHierarchyBuilder.h +++ b/src/db/db/dbHierarchyBuilder.h @@ -314,6 +314,25 @@ public: m_wants_all_cells = f; } + /** + * @brief Sets the "sparse array" limit + * + * Sparse arrays are instance arrays whose bounding box is no longer a + * good approximation of the covered area. The "sparse array ratio" is + * the area of the bounding box divided by the area of the bounding box + * of a single instance. + * + * Arrays above this limit will be resolved into single instances. + * + * Setting this value to 0 will resolve all arrays. Setting this + * value to a negative value will never split arrays. The latter + * is the default. + */ + void set_sparse_array_limit (double l) + { + m_sparse_array_limit = l; + } + /** * @brief Reset the builder - performs a new initial pass */ @@ -440,6 +459,8 @@ private: db::Cell *mp_initial_cell; db::ICplxTrans m_trans; + + double m_sparse_array_limit; }; } diff --git a/src/db/db/gsiDeclDbDeepShapeStore.cc b/src/db/db/gsiDeclDbDeepShapeStore.cc index 552b07f2d..adde28392 100644 --- a/src/db/db/gsiDeclDbDeepShapeStore.cc +++ b/src/db/db/gsiDeclDbDeepShapeStore.cc @@ -126,6 +126,26 @@ Class decl_dbDeepShapeStore ("db", "DeepShapeStore", "@brief Gets a flag wether to copy the full hierarchy for the working layouts\n" "This attribute has been introduced in version 0.28.10." ) + + gsi::method ("sparse_array_limit=", &db::DeepShapeStore::set_sparse_array_limit, gsi::arg ("limit"), + "@brief Sets the \"sparse array\" limit\n" + "\n" + "Sparse arrays are instance arrays whose bounding box is no longer a\n" + "good approximation of the covered area. The \"sparse array ratio\" is\n" + "the area of the bounding box divided by the area of the bounding box\n" + "of a single instance.\n" + "\n" + "Arrays above this limit will be resolved into single instances.\n" + "\n" + "Setting this value to 0 will resolve all arrays. Setting this\n" + "value to a negative value will never split arrays. The latter\n" + "is the default.\n" + "\n" + "This attribute has been introduced in version 0.30.8." + ) + + gsi::method ("sparse_array_limit", &db::DeepShapeStore::sparse_array_limit, + "@brief Gets the \"sparse array\" limit\n" + "This attribute has been introduced in version 0.30.8." + ) + gsi::method ("reject_odd_polygons=", &db::DeepShapeStore::set_reject_odd_polygons, gsi::arg ("count"), "@brief Sets a flag indicating whether to reject odd polygons\n" "\n"