From 23b314345139f03bf6af4d458cff0cf4a1a30a14 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 25 Jan 2026 13:36:22 +0100 Subject: [PATCH] Report flat count in deep mode, optimize hierarchy handling 1. In deep mode, the count report column will report hierarchical and flat counts 2. XOR is shortcut evaluated with one empty input. The default implementation does that internally, but at the cost of mapping to the internal working layout which spoils hierarchy. --- src/buddies/src/bd/strmxor.cc | 87 +++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index 7df5be64b..6720d58e8 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -29,6 +29,7 @@ #include "dbSaveLayoutOptions.h" #include "dbRegion.h" #include "dbDeepShapeStore.h" +#include "dbCellGraphUtils.h" #include "gsiExpression.h" #include "tlCommandLineParser.h" #include "tlThreads.h" @@ -271,12 +272,13 @@ HealingTileLayoutOutputReceiver::output (const db::Box &box) struct ResultDescriptor { ResultDescriptor () - : shape_count (0), layer_a (-1), layer_b (-1), layer_output (-1), layout (0), top_cell (0) + : shape_count (0), flat_shape_count (0), layer_a (-1), layer_b (-1), layer_output (-1), layout (0), top_cell (0) { // .. nothing yet .. } size_t shape_count; + size_t flat_shape_count; int layer_a; int layer_b; int layer_output; @@ -296,6 +298,20 @@ struct ResultDescriptor } } + size_t flat_count () const + { + if (layout && layer_output >= 0) { + size_t res = 0; + db::CellCounter counter (layout, top_cell); + for (db::Layout::const_iterator c = layout->begin (); c != layout->end (); ++c) { + res += c->shapes (layer_output).size () * counter.weight (c->cell_index ()); + } + return res; + } else { + return flat_shape_count; + } + } + bool is_empty () const { if (layout && layer_output >= 0) { @@ -586,12 +602,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) const char *line_format = " %-10s %-12s %s"; - std::string headline; - if (deep) { - headline = tl::sprintf (line_format, tl::to_string (tr ("Layer")), tl::to_string (tr ("Output")), tl::to_string (tr ("Differences (hierarchical shape count)"))); - } else { - headline = tl::sprintf (line_format, tl::to_string (tr ("Layer")), tl::to_string (tr ("Output")), tl::to_string (tr ("Differences (shape count)"))); - } + std::string headline = tl::sprintf (line_format, tl::to_string (tr ("Layer")), tl::to_string (tr ("Output")), tl::to_string (tr ("Differences (shape count)"))); const char *sep = " ----------------------------------------------------------------"; @@ -619,7 +630,11 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) if (r->second.layer_output >= 0 && r->second.layout) { out = r->second.layout->get_properties (r->second.layer_output).to_string (); } - value = tl::to_string (r->second.count ()); + if (deep) { + value = tl::sprintf (tl::to_string (tr ("%lu (hierarchical) %lu (flat)")), r->second.count (), r->second.flat_count ()); + } else { + value = tl::to_string (r->second.count ()); + } } if (! value.empty ()) { tl::info << tl::sprintf (line_format, r->first.second.to_string (), out, value); @@ -846,29 +861,40 @@ public: tl::SelfTimer timer (tl::verbosity () >= 11, "XOR on layer " + m_layer_props.to_string ()); - db::RecursiveShapeIterator ri_a, ri_b; - - if (m_la >= 0) { - ri_a = db::RecursiveShapeIterator (*mp_xor_data->layout_a, mp_xor_data->layout_a->cell (mp_xor_data->cell_a), m_la); - } else { - ri_a = db::RecursiveShapeIterator (*mp_xor_data->layout_a, mp_xor_data->layout_a->cell (mp_xor_data->cell_a), std::vector ()); - } - ri_a.set_for_merged_input (true); - - if (m_lb >= 0) { - ri_b = db::RecursiveShapeIterator (*mp_xor_data->layout_b, mp_xor_data->layout_b->cell (mp_xor_data->cell_b), m_lb); - } else { - ri_b = db::RecursiveShapeIterator (*mp_xor_data->layout_b, mp_xor_data->layout_b->cell (mp_xor_data->cell_b), std::vector ()); - } - ri_b.set_for_merged_input (true); - - db::Region in_a (ri_a, worker->dss (), db::ICplxTrans (mp_xor_data->layout_a->dbu () / m_dbu)); - db::Region in_b (ri_b, worker->dss (), db::ICplxTrans (mp_xor_data->layout_b->dbu () / m_dbu)); - db::Region xor_res; - { - tl::SelfTimer timer (tl::verbosity () >= 21, "Basic XOR on layer " + m_layer_props.to_string ()); - xor_res = in_a ^ in_b; + + if (m_la < 0) { + + tl_assert (m_lb >= 0); + + db::RecursiveShapeIterator ri_b (*mp_xor_data->layout_b, mp_xor_data->layout_b->cell (mp_xor_data->cell_b), m_lb); + xor_res = db::Region (ri_b, worker->dss (), db::ICplxTrans (mp_xor_data->layout_b->dbu () / m_dbu)); + + } else if (m_lb < 0) { + + db::RecursiveShapeIterator ri_a (*mp_xor_data->layout_a, mp_xor_data->layout_a->cell (mp_xor_data->cell_a), m_la); + xor_res = db::Region (ri_a, worker->dss (), db::ICplxTrans (mp_xor_data->layout_a->dbu () / m_dbu)); + + } else { + + db::RecursiveShapeIterator ri_a (*mp_xor_data->layout_a, mp_xor_data->layout_a->cell (mp_xor_data->cell_a), m_la); + db::RecursiveShapeIterator ri_b (*mp_xor_data->layout_b, mp_xor_data->layout_b->cell (mp_xor_data->cell_b), m_lb); + + db::Region in_a (ri_a, worker->dss (), db::ICplxTrans (mp_xor_data->layout_a->dbu () / m_dbu)); + db::Region in_b (ri_b, worker->dss (), db::ICplxTrans (mp_xor_data->layout_b->dbu () / m_dbu)); + + bool a_empty = in_a.empty (); + bool b_empty = in_b.empty (); + + if (a_empty && ! b_empty) { + xor_res = in_b; + } else if (! a_empty && b_empty) { + xor_res = in_a; + } else if (! a_empty && ! b_empty) { + tl::SelfTimer timer (tl::verbosity () >= 21, "Basic XOR on layer " + m_layer_props.to_string ()); + xor_res = in_a ^ in_b; + } + } int tol_index = 0; @@ -899,6 +925,7 @@ public: xor_res.insert_into (mp_xor_data->output_layout, mp_xor_data->output_cell, result.layer_output); } else { result.shape_count = xor_res.hier_count (); + result.flat_shape_count = xor_res.count (); } }