2929#include " dbSaveLayoutOptions.h"
3030#include " dbRegion.h"
3131#include " dbDeepShapeStore.h"
32+ #include " dbCellGraphUtils.h"
3233#include " gsiExpression.h"
3334#include " tlCommandLineParser.h"
3435#include " tlThreads.h"
3536#include " tlThreadedWorkers.h"
3637#include " tlTimer.h"
38+ #include " tlOptional.h"
3739
3840namespace {
3941
@@ -271,17 +273,19 @@ HealingTileLayoutOutputReceiver::output (const db::Box &box)
271273struct ResultDescriptor
272274{
273275 ResultDescriptor ()
274- : shape_count (0 ), layer_a (-1 ), layer_b (-1 ), layer_output (-1 ), layout (0 ), top_cell (0 )
276+ : shape_count (0 ), flat_shape_count ( 0 ), layer_a (-1 ), layer_b (-1 ), layer_output (-1 ), layout (0 ), top_cell (0 )
275277 {
276278 // .. nothing yet ..
277279 }
278280
279281 size_t shape_count;
282+ size_t flat_shape_count;
280283 int layer_a;
281284 int layer_b;
282285 int layer_output;
283286 db::Layout *layout;
284287 db::cell_index_type top_cell;
288+ tl::optional<db::Region> results;
285289
286290 size_t count () const
287291 {
@@ -296,6 +300,20 @@ struct ResultDescriptor
296300 }
297301 }
298302
303+ size_t flat_count () const
304+ {
305+ if (layout && layer_output >= 0 ) {
306+ size_t res = 0 ;
307+ db::CellCounter counter (layout, top_cell);
308+ for (db::Layout::const_iterator c = layout->begin (); c != layout->end (); ++c) {
309+ res += c->shapes (layer_output).size () * counter.weight (c->cell_index ());
310+ }
311+ return res;
312+ } else {
313+ return flat_shape_count;
314+ }
315+ }
316+
299317 bool is_empty () const
300318 {
301319 if (layout && layer_output >= 0 ) {
@@ -586,12 +604,8 @@ BD_PUBLIC int strmxor (int argc, char *argv[])
586604
587605 const char *line_format = " %-10s %-12s %s" ;
588606
589- std::string headline;
590- if (deep) {
591- headline = tl::sprintf (line_format, tl::to_string (tr (" Layer" )), tl::to_string (tr (" Output" )), tl::to_string (tr (" Differences (hierarchical shape count)" )));
592- } else {
593- headline = tl::sprintf (line_format, tl::to_string (tr (" Layer" )), tl::to_string (tr (" Output" )), tl::to_string (tr (" Differences (shape count)" )));
594- }
607+ std::string headline = tl::sprintf (line_format, tl::to_string (tr (" Layer" )), tl::to_string (tr (" Output" )),
608+ deep ? tl::to_string (tr (" Differences (hierarchical/flat count)" )) : tl::to_string (tr (" Differences (shape count)" )));
595609
596610 const char *sep = " ----------------------------------------------------------------" ;
597611
@@ -619,7 +633,11 @@ BD_PUBLIC int strmxor (int argc, char *argv[])
619633 if (r->second .layer_output >= 0 && r->second .layout ) {
620634 out = r->second .layout ->get_properties (r->second .layer_output ).to_string ();
621635 }
622- value = tl::to_string (r->second .count ());
636+ if (deep) {
637+ value = tl::sprintf (tl::to_string (tr (" %-6lu / %-6lu" )), r->second .count (), r->second .flat_count ());
638+ } else {
639+ value = tl::to_string (r->second .count ());
640+ }
623641 }
624642 if (! value.empty ()) {
625643 tl::info << tl::sprintf (line_format, r->first .second .to_string (), out, value);
@@ -767,8 +785,15 @@ bool run_tiled_xor (const XORData &xor_data)
767785 proc.execute (" Running XOR" );
768786 }
769787
788+ // no stored results currently
789+ for (std::map<std::pair<int , db::LayerProperties>, ResultDescriptor>::const_iterator r = xor_data.results ->begin (); r != xor_data.results ->end (); ++r) {
790+ tl_assert (! r->second .results .has_value ());
791+ }
792+
770793 // Determines the output status
771794 for (std::map<std::pair<int , db::LayerProperties>, ResultDescriptor>::const_iterator r = xor_data.results ->begin (); r != xor_data.results ->end () && result; ++r) {
795+ // no stored results currently
796+ tl_assert (! r->second .results .has_value ());
772797 result = r->second .is_empty ();
773798 }
774799
@@ -846,29 +871,40 @@ class XORTask
846871
847872 tl::SelfTimer timer (tl::verbosity () >= 11 , " XOR on layer " + m_layer_props.to_string ());
848873
849- db::RecursiveShapeIterator ri_a, ri_b ;
874+ db::Region xor_res ;
850875
851- if (m_la >= 0 ) {
852- ri_a = db::RecursiveShapeIterator (*mp_xor_data->layout_a , mp_xor_data->layout_a ->cell (mp_xor_data->cell_a ), m_la);
853- } else {
854- ri_a = db::RecursiveShapeIterator (*mp_xor_data->layout_a , mp_xor_data->layout_a ->cell (mp_xor_data->cell_a ), std::vector<unsigned int > ());
855- }
856- ri_a.set_for_merged_input (true );
876+ if (m_la < 0 ) {
877+
878+ tl_assert (m_lb >= 0 );
879+
880+ db::RecursiveShapeIterator ri_b (*mp_xor_data->layout_b , mp_xor_data->layout_b ->cell (mp_xor_data->cell_b ), m_lb);
881+ xor_res = db::Region (ri_b, worker->dss (), db::ICplxTrans (mp_xor_data->layout_b ->dbu () / m_dbu));
882+
883+ } else if (m_lb < 0 ) {
884+
885+ db::RecursiveShapeIterator ri_a (*mp_xor_data->layout_a , mp_xor_data->layout_a ->cell (mp_xor_data->cell_a ), m_la);
886+ xor_res = db::Region (ri_a, worker->dss (), db::ICplxTrans (mp_xor_data->layout_a ->dbu () / m_dbu));
857887
858- if (m_lb >= 0 ) {
859- ri_b = db::RecursiveShapeIterator (*mp_xor_data->layout_b , mp_xor_data->layout_b ->cell (mp_xor_data->cell_b ), m_lb);
860888 } else {
861- ri_b = db::RecursiveShapeIterator (*mp_xor_data->layout_b , mp_xor_data->layout_b ->cell (mp_xor_data->cell_b ), std::vector<unsigned int > ());
862- }
863- ri_b.set_for_merged_input (true );
864889
865- db::Region in_a (ri_a, worker->dss (), db::ICplxTrans (mp_xor_data->layout_a ->dbu () / m_dbu));
866- db::Region in_b (ri_b, worker->dss (), db::ICplxTrans (mp_xor_data->layout_b ->dbu () / m_dbu));
890+ db::RecursiveShapeIterator ri_a (*mp_xor_data->layout_a , mp_xor_data->layout_a ->cell (mp_xor_data->cell_a ), m_la);
891+ db::RecursiveShapeIterator ri_b (*mp_xor_data->layout_b , mp_xor_data->layout_b ->cell (mp_xor_data->cell_b ), m_lb);
892+
893+ db::Region in_a (ri_a, worker->dss (), db::ICplxTrans (mp_xor_data->layout_a ->dbu () / m_dbu));
894+ db::Region in_b (ri_b, worker->dss (), db::ICplxTrans (mp_xor_data->layout_b ->dbu () / m_dbu));
895+
896+ bool a_empty = in_a.empty ();
897+ bool b_empty = in_b.empty ();
898+
899+ if (a_empty && ! b_empty) {
900+ xor_res = in_b;
901+ } else if (! a_empty && b_empty) {
902+ xor_res = in_a;
903+ } else if (! a_empty && ! b_empty) {
904+ tl::SelfTimer timer (tl::verbosity () >= 21 , " Basic XOR on layer " + m_layer_props.to_string ());
905+ xor_res = in_a ^ in_b;
906+ }
867907
868- db::Region xor_res;
869- {
870- tl::SelfTimer timer (tl::verbosity () >= 21 , " Basic XOR on layer " + m_layer_props.to_string ());
871- xor_res = in_a ^ in_b;
872908 }
873909
874910 int tol_index = 0 ;
@@ -896,9 +932,12 @@ class XORTask
896932
897933 if (mp_xor_data->output_layout ) {
898934 result.layer_output = result.layout ->insert_layer (lp);
899- xor_res.insert_into (mp_xor_data->output_layout , mp_xor_data->output_cell , result.layer_output );
935+ if (! xor_res.empty ()) {
936+ result.results = xor_res;
937+ }
900938 } else {
901939 result.shape_count = xor_res.hier_count ();
940+ result.flat_shape_count = xor_res.count ();
902941 }
903942 }
904943
@@ -964,6 +1003,22 @@ bool run_deep_xor (const XORData &xor_data)
9641003 job.start ();
9651004 job.wait ();
9661005
1006+ // Deliver the outputs
1007+ // NOTE: this is done single-threaded and in a delayed fashion as it is not efficient during
1008+ // computation and shifting hierarchy of the working layout
1009+
1010+ if (xor_data.output_layout ) {
1011+
1012+ tl::SelfTimer timer (tl::verbosity () >= 11 , " Result delivery" );
1013+
1014+ for (std::map<std::pair<int , db::LayerProperties>, ResultDescriptor>::const_iterator r = xor_data.results ->begin (); r != xor_data.results ->end (); ++r) {
1015+ if (r->second .results .has_value ()) {
1016+ r->second .results .value ().insert_into (xor_data.output_layout , xor_data.output_cell , r->second .layer_output );
1017+ }
1018+ }
1019+
1020+ }
1021+
9671022 // Determine the output status
9681023
9691024 bool result = (xor_data.layers_missing == 0 );
0 commit comments