From 67575a7ea21e414c39d497121ec79b91eaa821a1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 6 Sep 2019 22:18:13 +0200 Subject: [PATCH 1/3] WIP: strmxor.cc - deep mode implemented. Not tested. --- src/buddies/src/bd/strmxor.cc | 450 +++++++++++++++++++++++----------- 1 file changed, 312 insertions(+), 138 deletions(-) diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index 13fa5d570..da2092718 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -26,6 +26,8 @@ #include "dbReader.h" #include "dbWriter.h" #include "dbSaveLayoutOptions.h" +#include "dbRegion.h" +#include "dbDeepShapeStore.h" #include "gsiExpression.h" #include "tlCommandLineParser.h" @@ -57,8 +59,8 @@ class CountingReceiver : public db::TileOutputReceiver { public: - CountingReceiver () - : m_count (0) + CountingReceiver (size_t *count) + : mp_count (count) { // .. nothing yet .. } @@ -67,27 +69,22 @@ public: { CountingInserter inserter; db::insert_var (inserter, obj, tile, clip); - m_count += inserter.count (); - } - - size_t count () const - { - return m_count; + *mp_count += inserter.count (); } private: - size_t m_count; + size_t *mp_count; }; struct ResultDescriptor { ResultDescriptor () - : layer_a (-1), layer_b (-1), layer_output (-1), layout (0), top_cell (0) + : shape_count (0), layer_a (-1), layer_b (-1), layer_output (-1), layout (0), top_cell (0) { // .. nothing yet .. } - tl::shared_ptr counter; + size_t shape_count; int layer_a; int layer_b; int layer_output; @@ -100,10 +97,8 @@ struct ResultDescriptor // NOTE: this assumes the output is flat tl_assert (layout->cells () == 1); return layout->cell (top_cell).shapes (layer_output).size (); - } else if (counter) { - return counter->count (); } else { - return 0; + return shape_count; } } @@ -113,14 +108,40 @@ struct ResultDescriptor // NOTE: this assumes the output is flat tl_assert (layout->cells () == 1); return layout->cell (top_cell).shapes (layer_output).empty (); - } else if (counter) { - return counter->count () == 0; } else { - return true; + return shape_count == 0; } } }; +struct XORData +{ + XORData () + : layout_a (0), layout_b (0), cell_a (0), cell_b (0), + tolerance_bump (0), + dont_summarize_missing_layers (false), silent (false), no_summary (false), + threads (0), + tile_size (0.0), output_layout (0), output_cell (0) + { } + + db::Layout *layout_a, *layout_b; + db::cell_index_type cell_a, cell_b; + std::vector tolerances; + int tolerance_bump; + bool dont_summarize_missing_layers; + bool silent; + bool no_summary; + int threads; + double tile_size; + db::Layout *output_layout; + db::cell_index_type output_cell; + std::map > l2l_map; + std::map, ResultDescriptor> *results; +}; + +static bool run_tiled_xor (const XORData &xor_data); +static bool run_deep_xor (const XORData &xor_data); + BD_PUBLIC int strmxor (int argc, char *argv[]) { gsi::initialize_expressions (); @@ -140,6 +161,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) bool dont_summarize_missing_layers = false; bool silent = false; bool no_summary = false; + bool deep = false; std::vector tolerances; int tolerance_bump = 10000; int threads = 1; @@ -163,6 +185,10 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) << tl::arg ("-tb|--top-b=name", &top_b, "Specifies the top cell for the second layout", "See --top-a for details." ) + << tl::arg ("-d|--deep", &deep, "Deep (hierarchical mode)", + "Enables hierarchical XOR (experimental). In this mode, tiling is not supported " + "and the tiling arguments are ignored." + ) << tl::arg ("-s|--silent", &silent, "Silent mode", "In silent mode, no summary is printed, but the exit code indicates whether " "the layouts are the same (0) or differences exist (> 0)." @@ -277,135 +303,40 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) l2l_map.insert (std::make_pair (*(*l).second, std::make_pair (-1, -1))).first->second.second = (*l).first; } - db::TilingProcessor proc; - proc.set_dbu (std::min (layout_a.dbu (), layout_b.dbu ())); - proc.set_threads (std::max (1, threads)); - if (tile_size > db::epsilon) { - if (tl::verbosity () >= 20) { - tl::log << "Tile size: " << tile_size; - } - proc.tile_size (tile_size, tile_size); - } - - proc.tile_border (tolerances.back () * 2.0, tolerances.back () * 2.0); - if (tl::verbosity () >= 20) { - tl::log << "Tile border: " << tolerances.back () * 2.0; - } - - if (tl::verbosity () >= 20) { - tl::log << "Database unit: " << proc.dbu (); - tl::log << "Threads: " << threads; - tl::log << "Layer bump for tolerance: " << tolerance_bump; - } - std::auto_ptr output_layout; db::cell_index_type output_top = 0; if (! output.empty ()) { output_layout.reset (new db::Layout ()); - output_layout->dbu (proc.dbu ()); output_top = output_layout->add_cell ("XOR"); } std::map, ResultDescriptor> results; - bool result = true; + XORData xor_data; + xor_data.layout_a = &layout_a; + xor_data.cell_a = index_a.second; + xor_data.layout_b = &layout_b; + xor_data.cell_b = index_b.second; + xor_data.tolerances = tolerances; + xor_data.tolerance_bump = tolerance_bump; + xor_data.dont_summarize_missing_layers = dont_summarize_missing_layers; + xor_data.silent = silent; + xor_data.no_summary = no_summary; + xor_data.threads = threads; + xor_data.tile_size = tile_size; + xor_data.output_layout = output_layout.get (); + xor_data.l2l_map = l2l_map; + xor_data.results = &results; - int index = 1; + // Runs the XOR - for (std::map >::const_iterator ll = l2l_map.begin (); ll != l2l_map.end (); ++ll) { + bool result; - if ((ll->second.first < 0 || ll->second.second < 0) && ! dont_summarize_missing_layers) { - - if (ll->second.first < 0) { - (silent ? tl::log : tl::warn) << "Layer " << ll->first.to_string () << " is not present in first layout, but in second"; - } else { - (silent ? tl::log : tl::warn) << "Layer " << ll->first.to_string () << " is not present in second layout, but in first"; - } - - result = false; - - int tol_index = 0; - for (std::vector::const_iterator t = tolerances.begin (); t != tolerances.end (); ++t) { - - ResultDescriptor &result = results.insert (std::make_pair (std::make_pair (tol_index, ll->first), ResultDescriptor ())).first->second; - result.layer_a = ll->second.first; - result.layer_b = ll->second.second; - result.layout = output_layout.get (); - result.top_cell = output_top; - - ++tol_index; - - } - - } else { - - std::string in_a = "a" + tl::to_string (index); - std::string in_b = "b" + tl::to_string (index); - - if (ll->second.first < 0) { - proc.input (in_a, db::RecursiveShapeIterator ()); - } else { - proc.input (in_a, db::RecursiveShapeIterator (layout_a, layout_a.cell (index_a.second), ll->second.first)); - } - - if (ll->second.second < 0) { - proc.input (in_b, db::RecursiveShapeIterator ()); - } else { - proc.input (in_b, db::RecursiveShapeIterator (layout_b, layout_b.cell (index_b.second), ll->second.second)); - } - - std::string expr = "var x=" + in_a + "^" + in_b + "; "; - - int tol_index = 0; - for (std::vector::const_iterator t = tolerances.begin (); t != tolerances.end (); ++t) { - - std::string out = "o" + tl::to_string (index) + "_" + tl::to_string (tol_index + 1); - - db::LayerProperties lp = ll->first; - if (lp.layer >= 0) { - lp.layer += tol_index * tolerance_bump; - } - - ResultDescriptor &result = results.insert (std::make_pair (std::make_pair (tol_index, ll->first), ResultDescriptor ())).first->second; - result.layer_a = ll->second.first; - result.layer_b = ll->second.second; - result.layout = output_layout.get (); - result.top_cell = output_top; - - if (result.layout) { - result.layer_output = result.layout->insert_layer (lp); - proc.output (out, *result.layout, result.top_cell, result.layer_output); - } else { - CountingReceiver *counter = new CountingReceiver (); - result.counter = counter; - proc.output (out, 0, counter, db::ICplxTrans ()); - } - - if (*t > db::epsilon) { - expr += "x=x.sized(-round(" + tl::to_string (*t) + "/_dbu)/2).sized(round(" + tl::to_string (*t) + "/_dbu)/2); "; - } - expr += "_output(" + out + ",x); "; - - ++tol_index; - - } - - if (tl::verbosity () >= 20) { - tl::log << "Running expression: '" << expr << "' for layer " << ll->first; - } - proc.queue (expr); - - } - - ++index; - - } - - // Runs the processor - - if ((! silent && ! no_summary) || result || output_layout.get ()) { - proc.execute ("Running XOR"); + if (deep) { + result = run_deep_xor (xor_data); + } else { + result = run_tiled_xor (xor_data); } // Writes the output layout @@ -421,11 +352,6 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) } - // Determines the output status - for (std::map, ResultDescriptor>::const_iterator r = results.begin (); r != results.end () && result; ++r) { - result = r->second.is_empty (); - } - if (! silent && ! no_summary) { if (result) { @@ -476,3 +402,251 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) return result ? 0 : 1; } + +bool run_tiled_xor (const XORData &xor_data) +{ + db::TilingProcessor proc; + proc.set_dbu (std::min (xor_data.layout_a->dbu (), xor_data.layout_b->dbu ())); + proc.set_threads (std::max (1, xor_data.threads)); + if (xor_data.tile_size > db::epsilon) { + if (tl::verbosity () >= 20) { + tl::log << "Tile size: " << xor_data.tile_size; + } + proc.tile_size (xor_data.tile_size, xor_data.tile_size); + } + + proc.tile_border (xor_data.tolerances.back () * 2.0, xor_data.tolerances.back () * 2.0); + if (tl::verbosity () >= 20) { + tl::log << "Tile border: " << xor_data.tolerances.back () * 2.0; + } + + if (tl::verbosity () >= 20) { + tl::log << "Database unit: " << proc.dbu (); + tl::log << "Threads: " << xor_data.threads; + tl::log << "Layer bump for tolerance: " << xor_data.tolerance_bump; + } + + if (xor_data.output_layout) { + xor_data.output_layout->dbu (proc.dbu ()); + } + + bool result = true; + + int index = 1; + + std::list > counters; + + for (std::map >::const_iterator ll = xor_data.l2l_map.begin (); ll != xor_data.l2l_map.end (); ++ll) { + + if ((ll->second.first < 0 || ll->second.second < 0) && ! xor_data.dont_summarize_missing_layers) { + + if (ll->second.first < 0) { + (xor_data.silent ? tl::log : tl::warn) << "Layer " << ll->first.to_string () << " is not present in first layout, but in second"; + } else { + (xor_data.silent ? tl::log : tl::warn) << "Layer " << ll->first.to_string () << " is not present in second layout, but in first"; + } + + result = false; + + int tol_index = 0; + for (std::vector::const_iterator t = xor_data.tolerances.begin (); t != xor_data.tolerances.end (); ++t) { + + ResultDescriptor &result = xor_data.results->insert (std::make_pair (std::make_pair (tol_index, ll->first), ResultDescriptor ())).first->second; + result.layer_a = ll->second.first; + result.layer_b = ll->second.second; + result.layout = xor_data.output_layout; + result.top_cell = xor_data.output_cell; + + ++tol_index; + + } + + } else { + + std::string in_a = "a" + tl::to_string (index); + std::string in_b = "b" + tl::to_string (index); + + if (ll->second.first < 0) { + proc.input (in_a, db::RecursiveShapeIterator ()); + } else { + proc.input (in_a, db::RecursiveShapeIterator (*xor_data.layout_a, xor_data.layout_a->cell (xor_data.cell_a), ll->second.first)); + } + + if (ll->second.second < 0) { + proc.input (in_b, db::RecursiveShapeIterator ()); + } else { + proc.input (in_b, db::RecursiveShapeIterator (*xor_data.layout_b, xor_data.layout_b->cell (xor_data.cell_b), ll->second.second)); + } + + std::string expr = "var x=" + in_a + "^" + in_b + "; "; + + int tol_index = 0; + for (std::vector::const_iterator t = xor_data.tolerances.begin (); t != xor_data.tolerances.end (); ++t) { + + std::string out = "o" + tl::to_string (index) + "_" + tl::to_string (tol_index + 1); + + db::LayerProperties lp = ll->first; + if (lp.layer >= 0) { + lp.layer += tol_index * xor_data.tolerance_bump; + } + + ResultDescriptor &result = xor_data.results->insert (std::make_pair (std::make_pair (tol_index, ll->first), ResultDescriptor ())).first->second; + result.layer_a = ll->second.first; + result.layer_b = ll->second.second; + result.layout = xor_data.output_layout; + result.top_cell = xor_data.output_cell; + + if (result.layout) { + result.layer_output = result.layout->insert_layer (lp); + proc.output (out, *result.layout, result.top_cell, result.layer_output); + } else { + CountingReceiver *counter = new CountingReceiver (&result.shape_count); + counters.push_back (tl::shared_ptr (counter)); + proc.output (out, 0, counter, db::ICplxTrans ()); + } + + if (*t > db::epsilon) { + expr += "x=x.sized(-round(" + tl::to_string (*t) + "/_dbu)/2).sized(round(" + tl::to_string (*t) + "/_dbu)/2); "; + } + expr += "_output(" + out + ",x); "; + + ++tol_index; + + } + + if (tl::verbosity () >= 20) { + tl::log << "Running expression: '" << expr << "' for layer " << ll->first; + } + proc.queue (expr); + + } + + ++index; + + } + + // Runs the processor + + if ((! xor_data.silent && ! xor_data.no_summary) || result || xor_data.output_layout) { + proc.execute ("Running XOR"); + } + + // Determines the output status + for (std::map, ResultDescriptor>::const_iterator r = xor_data.results->begin (); r != xor_data.results->end () && result; ++r) { + result = r->second.is_empty (); + } + + return result; +} + +bool run_deep_xor (const XORData &xor_data) +{ + db::DeepShapeStore dss; + dss.set_threads (xor_data.threads); + + double dbu = std::min (xor_data.layout_a->dbu (), xor_data.layout_b->dbu ()); + + if (tl::verbosity () >= 20) { + tl::log << "Database unit: " << dbu; + tl::log << "Threads: " << xor_data.threads; + tl::log << "Layer bump for tolerance: " << xor_data.tolerance_bump; + } + + if (xor_data.output_layout) { + xor_data.output_layout->dbu (dbu); + } + + bool result = true; + + int index = 1; + + for (std::map >::const_iterator ll = xor_data.l2l_map.begin (); ll != xor_data.l2l_map.end (); ++ll) { + + if ((ll->second.first < 0 || ll->second.second < 0) && ! xor_data.dont_summarize_missing_layers) { + + if (ll->second.first < 0) { + (xor_data.silent ? tl::log : tl::warn) << "Layer " << ll->first.to_string () << " is not present in first layout, but in second"; + } else { + (xor_data.silent ? tl::log : tl::warn) << "Layer " << ll->first.to_string () << " is not present in second layout, but in first"; + } + + result = false; + + int tol_index = 0; + for (std::vector::const_iterator t = xor_data.tolerances.begin (); t != xor_data.tolerances.end (); ++t) { + + ResultDescriptor &result = xor_data.results->insert (std::make_pair (std::make_pair (tol_index, ll->first), ResultDescriptor ())).first->second; + result.layer_a = ll->second.first; + result.layer_b = ll->second.second; + result.layout = xor_data.output_layout; + result.top_cell = xor_data.output_cell; + + ++tol_index; + + } + + } else { + + db::RecursiveShapeIterator ri_a, ri_b; + + if (ll->second.first >= 0) { + ri_a = db::RecursiveShapeIterator (*xor_data.layout_a, xor_data.layout_a->cell (xor_data.cell_a), ll->second.first); + } + + if (ll->second.second < 0) { + ri_b = db::RecursiveShapeIterator (*xor_data.layout_b, xor_data.layout_b->cell (xor_data.cell_b), ll->second.second); + } + + db::Region in_a (ri_a, dss, db::ICplxTrans (xor_data.layout_a->dbu () / dbu)); + db::Region in_b (ri_b, dss, db::ICplxTrans (xor_data.layout_b->dbu () / dbu)); + + db::Region xor_res; + xor_res = in_a ^ in_b; + + int tol_index = 0; + for (std::vector::const_iterator t = xor_data.tolerances.begin (); t != xor_data.tolerances.end (); ++t) { + + if (tl::verbosity () >= 20) { + tl::log << "Running XOR on layer " << ll->first.to_string () << " with tolerance " << *t; + } + + db::LayerProperties lp = ll->first; + if (lp.layer >= 0) { + lp.layer += tol_index * xor_data.tolerance_bump; + } + + ResultDescriptor &result = xor_data.results->insert (std::make_pair (std::make_pair (tol_index, ll->first), ResultDescriptor ())).first->second; + result.layer_a = ll->second.first; + result.layer_b = ll->second.second; + result.layout = xor_data.output_layout; + result.top_cell = xor_data.output_cell; + + if (*t > db::epsilon) { + xor_res.size (-db::coord_traits::rounded (0.5 * *t / dbu)); + xor_res.size (db::coord_traits::rounded (0.5 * *t / dbu)); + } + + if (xor_data.output_layout) { + result.layer_output = result.layout->insert_layer (lp); + xor_res.insert_into (xor_data.output_layout, xor_data.output_cell, result.layer_output); + } else { + result.shape_count = xor_res.size (); + } + + ++tol_index; + + } + + } + + ++index; + + } + + // Determines the output status + for (std::map, ResultDescriptor>::const_iterator r = xor_data.results->begin (); r != xor_data.results->end () && result; ++r) { + result = r->second.is_empty (); + } + + return result; +} From 26f8fc5c830a5af48fe090d5b6402023351b63e1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 7 Sep 2019 21:27:12 +0200 Subject: [PATCH 2/3] Bug fixed strmxor with deep mode, added tests. --- src/buddies/src/bd/strmxor.cc | 21 +- src/buddies/unit_tests/bdStrmxorTests.cc | 318 ++++++++++++++++++++++- testdata/bd/strmxor_au1d.oas | Bin 0 -> 818 bytes testdata/bd/strmxor_au2d.oas | Bin 0 -> 843 bytes testdata/bd/strmxor_au3d.oas | Bin 0 -> 818 bytes testdata/bd/strmxor_au4d.oas | Bin 0 -> 1033 bytes testdata/bd/strmxor_au5d.oas | Bin 0 -> 1026 bytes testdata/bd/strmxor_au6d.oas | Bin 0 -> 498 bytes 8 files changed, 321 insertions(+), 18 deletions(-) create mode 100644 testdata/bd/strmxor_au1d.oas create mode 100644 testdata/bd/strmxor_au2d.oas create mode 100644 testdata/bd/strmxor_au3d.oas create mode 100644 testdata/bd/strmxor_au4d.oas create mode 100644 testdata/bd/strmxor_au5d.oas create mode 100644 testdata/bd/strmxor_au6d.oas diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index da2092718..bc592af0b 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -94,9 +94,11 @@ struct ResultDescriptor size_t count () const { if (layout && layer_output >= 0) { - // NOTE: this assumes the output is flat - tl_assert (layout->cells () == 1); - return layout->cell (top_cell).shapes (layer_output).size (); + size_t res = 0; + for (db::Layout::const_iterator c = layout->begin (); c != layout->end (); ++c) { + res += c->shapes (layer_output).size (); + } + return res; } else { return shape_count; } @@ -105,9 +107,12 @@ struct ResultDescriptor bool is_empty () const { if (layout && layer_output >= 0) { - // NOTE: this assumes the output is flat - tl_assert (layout->cells () == 1); - return layout->cell (top_cell).shapes (layer_output).empty (); + for (db::Layout::const_iterator c = layout->begin (); c != layout->end (); ++c) { + if (! c->shapes (layer_output).empty ()) { + return false; + } + } + return true; } else { return shape_count == 0; } @@ -185,7 +190,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) << tl::arg ("-tb|--top-b=name", &top_b, "Specifies the top cell for the second layout", "See --top-a for details." ) - << tl::arg ("-d|--deep", &deep, "Deep (hierarchical mode)", + << tl::arg ("-u|--deep", &deep, "Deep (hierarchical mode)", "Enables hierarchical XOR (experimental). In this mode, tiling is not supported " "and the tiling arguments are ignored." ) @@ -593,7 +598,7 @@ bool run_deep_xor (const XORData &xor_data) ri_a = db::RecursiveShapeIterator (*xor_data.layout_a, xor_data.layout_a->cell (xor_data.cell_a), ll->second.first); } - if (ll->second.second < 0) { + if (ll->second.second >= 0) { ri_b = db::RecursiveShapeIterator (*xor_data.layout_b, xor_data.layout_b->cell (xor_data.cell_b), ll->second.second); } diff --git a/src/buddies/unit_tests/bdStrmxorTests.cc b/src/buddies/unit_tests/bdStrmxorTests.cc index 27871f521..2ccf0a4d1 100644 --- a/src/buddies/unit_tests/bdStrmxorTests.cc +++ b/src/buddies/unit_tests/bdStrmxorTests.cc @@ -30,7 +30,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[]); -TEST(0) +TEST(0_Basic_Flat) { tl::CaptureChannel cap; @@ -51,7 +51,28 @@ TEST(0) ); } -TEST(1A) +TEST(0_Basic_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in1.gds"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", input_a.c_str (), input_b.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 0); + + EXPECT_EQ (cap.captured_text (), + "No differences found\n" + ); +} + +TEST(1A_Flat) { tl::CaptureChannel cap; @@ -93,7 +114,49 @@ TEST(1A) ); } -TEST(1B) +TEST(1A_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/bd/strmxor_au1d.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "--deep", input_a.c_str (), input_b.c_str (), output.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (this, layout, au, db::NoNormalization); + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + "Result summary (layers without differences are not shown):\n" + "\n" + " Layer Output Differences (shape count)\n" + " -------------------------------------------------------\n" + " 3/0 3/0 3\n" + " 6/0 6/0 314\n" + " 8/1 8/1 1\n" + " 10/0 - (no such layer in first layout)\n" + "\n" + ); +} + +TEST(1B_Flat) { tl::CaptureChannel cap; @@ -123,7 +186,37 @@ TEST(1B) ); } -TEST(1C) +TEST(1B_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", input_a.c_str (), input_b.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + "Result summary (layers without differences are not shown):\n" + "\n" + " Layer Output Differences (shape count)\n" + " -------------------------------------------------------\n" + " 3/0 - 30\n" + " 6/0 - 314\n" + " 8/1 - 1\n" + " 10/0 - (no such layer in first layout)\n" + "\n" + ); +} + +TEST(1C_Flat) { tl::CaptureChannel cap; @@ -144,7 +237,28 @@ TEST(1C) ); } -TEST(1D) +TEST(1C_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", "--no-summary", input_a.c_str (), input_b.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + ); +} + +TEST(1D_Flat) { tl::CaptureChannel cap; @@ -162,7 +276,25 @@ TEST(1D) EXPECT_EQ (cap.captured_text (), ""); } -TEST(2) +TEST(1D_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", "-s", input_a.c_str (), input_b.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + EXPECT_EQ (cap.captured_text (), ""); +} + +TEST(2_Flat) { tl::CaptureChannel cap; @@ -195,7 +327,40 @@ TEST(2) ); } -TEST(3) +TEST(2_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/bd/strmxor_au2d.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", "--no-summary", "-l", input_a.c_str (), input_b.c_str (), output.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (this, layout, au, db::NoNormalization); + EXPECT_EQ (cap.captured_text (), + "" + ); +} + +TEST(3_Flat) { tl::CaptureChannel cap; @@ -228,7 +393,41 @@ TEST(3) ); } -TEST(4) +TEST(3_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/bd/strmxor_au3d.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + // NOTE: -p is ignored in deep mode + const char *argv[] = { "x", "-u", "--no-summary", "-p=1.0", "-n=4", input_a.c_str (), input_b.c_str (), output.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (this, layout, au, db::NoNormalization); + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + ); +} + +TEST(4_Flat) { tl::CaptureChannel cap; @@ -261,7 +460,40 @@ TEST(4) ); } -TEST(5) +TEST(4_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/bd/strmxor_au4d.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", "--no-summary", "-p=1.0", "-n=4", "-t=0.0,0.005,0.01,0.02,0.09,0.1", input_a.c_str (), input_b.c_str (), output.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (this, layout, au, db::NoNormalization); + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + ); +} + +TEST(5_Flat) { tl::CaptureChannel cap; @@ -294,7 +526,40 @@ TEST(5) ); } -TEST(6) +TEST(5_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/bd/strmxor_au5d.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", "--no-summary", "-b=1000", "-t=0.0,0.005,0.01,0.02,0.09,0.1", input_a.c_str (), input_b.c_str (), output.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (this, layout, au, db::NoNormalization); + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + ); +} + +TEST(6_Flat) { tl::CaptureChannel cap; @@ -326,3 +591,36 @@ TEST(6) "Layer 10/0 is not present in first layout, but in second\n" ); } + +TEST(6_Deep) +{ + tl::CaptureChannel cap; + + std::string input_a = tl::testsrc (); + input_a += "/testdata/bd/strmxor_in1.gds"; + + std::string input_b = tl::testsrc (); + input_b += "/testdata/bd/strmxor_in2.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/bd/strmxor_au6d.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + const char *argv[] = { "x", "-u", "--no-summary", "-ta=INV2", "-tb=2VNI", input_a.c_str (), input_b.c_str (), output.c_str () }; + + EXPECT_EQ (strmxor (sizeof (argv) / sizeof (argv[0]), (char **) argv), 1); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (this, layout, au, db::NoNormalization); + EXPECT_EQ (cap.captured_text (), + "Layer 10/0 is not present in first layout, but in second\n" + ); +} diff --git a/testdata/bd/strmxor_au1d.oas b/testdata/bd/strmxor_au1d.oas new file mode 100644 index 0000000000000000000000000000000000000000..012da78437b2662a4b065b156b0b1dac5ed20c9f GIT binary patch literal 818 zcmd^*KTE?<6vf|r@ui7POk3|m8-iUF9JHvDpdv+s1~iqX{+qJ6_$`V!bf{Y=rwR^r zD^4yhQlS-x4h}kW>kz@AIJJY|OJYUAZ{VHI%f09PZtj$0Zd9pNAg(AU%pD)PgQ!#;w*CgU7kSjJo_hPq>FIV?F~#`AI>(E{;Ndq{NY2 zS5ojI-y{Nks=x<13;jHdci+aL3e$rO=+M{S{SJl3N;yd)90F~fpt~{O)}4e~%~J-x zk_c6;PXh*&XOlq8*3>`<$BWK~VwNaki6eS529!Mn} zprYWB{`Uc(E)S@W2~I7g!i>knJ^%ZF^iIOVLZ1_S$#2-!dlP}|(57BavLy-gGaY(0 N;UaYfr0|~$p-*XN0nV3!OYIwXTP4=Qvpnd~9ZE2$1G^c(a}=jq;ieplyS;O=-2s+GVC z%q-;_>kmn^K>jR8+CjKe*$V@2%Xc?J&#${%ZY|vPHtR3cjAJ@!`<4H%0Y_$ouwH!` zK6kgb4Zc^caZ#^T{D5aX|Mepte=&(k^AR~ybTW~J{6SkGvdjr(LjfOnWa#9YEy~C7 zyH5vpr)aW#pX%xm7Uw0)3eLk++_0&jDjC8=O6S}fDaqr#Bb}ahxxsKpKBYJVC)#&| z#QJ0jdbtK7QMXHQrF||W`q+RQcAD;^8Fqi(g$~@Gd%#%y_`5$A(0|q{vIT^|$Y$ir zop^1s3g=d2%=a1!bgY?37|;?u?Kk5{kxs{gJ07kz@AIJJY|OJYUAZ{VHI%f09PZtj$0Zd9pNAg(AU%pD)PgQ!#;w*CgU7kSjJo_hPq>FIV?F~#`AI>(E{;Ndq{NY2 zS5ojI-y{Nks=x<13;jHdci+aL3e$rO=+M{S{SJl3N;yd)90F~fpt~{O)}4e~%~J-x zk_c6;PXh*&XOlq8*3>`<$BWK~VwNaki6eS529!Mn} zprYWB{`Uc(E)S@W2~I7g!i>knJ^%ZF^iIOVLZ1_S$#2-!dlP}|(57BavLy-gGaY(0 N;UaYfr0|~$p-*?^@LlU)1qNTR zopSMxbE~kqsY%<#l0?g;yk$#srgiVSB>qHE6eoPtkX1D1dg4)CMtn^|n0S=EmV8Y` zM*-7!v)bczQ_(@zBcQt%B&fi(m;dNXeV-_@mS_Y zGsXhHZ)3tQPzk?RFlm8uI_!AZU)&ANwvxcxlNANIpGkc=kW!gXrl$j7oybh}PzTj& zHsmq~eZ*D+T5)2*+vw zpB;S;D=^wG)Po&>1L5k1g5mNW_${fCeZx53vp8;wSJD=*q}wJO_n%6{{ht>?e*vd? BOg{hs literal 0 HcmV?d00001 diff --git a/testdata/bd/strmxor_au5d.oas b/testdata/bd/strmxor_au5d.oas new file mode 100644 index 0000000000000000000000000000000000000000..fed55a71321fc55a3d4f6f0d9ce31a4d367185a8 GIT binary patch literal 1026 zcmd^7L2DC16rP#wY&P9ZH`&b4BrM&Fq6aP3Q$R}zHq?bSk!;lVl#3Vt#a2Azkb;LC z#8ZME;w=>qf)qp|B+|o*9^xSoA;O9xv8Uuv@Xc;hTJRtE_VV6-?|t7lZ|0(t-?Fb3 zbB^uA=CQQ0d=2>#bT&+$aVlH6?TTY>6!Pm8yHL(=yr2rLouB2QBzjYm>Y?Q4H@w@31Q+<_CoSC z6&;Z{&x*Q>dzn_6ul|gjqUaogKkFR7UF7(=6(fl*RuzxMXTjHGU}Y0}OePd7$YW#9 z%>#WP2gNg!o1JKXg}@BIiJ^y8qhB;6@@kTG7HVJ&@`lB}M&B4g{#awjWG|ctGC+T& zSc_eraj+5naULI0)?KZqNd!dLAVbjmMKLzMzz%d@o6Xf^*3zdm&|r1iiJoXYlDXN^ zS>X4TF8l(O@OuT5HYlgVi3k0Kz0hns3A{a7QIPwQG?oJ?mHA|Px&YRR&QuQ#P_0=Z z$D#27P9G>8k#Nau3JM~H9S$;+r63*AUZxIr@;ic4Pc@fTle@H&V*4qV?nC-V^=LzO zskgLChsJjbqu&gdPN5X1I+2dQ&a!6KqwVC-@Sve#1)WW6XiT9LcO+aXux~*)Rs;C# x>a$pZ)qbKLd;vHRu5Kt8E^o(gOHJz~<9Hn5xDQX{9Xyei#qpC%#QmQGp}(drNB#f+ literal 0 HcmV?d00001 diff --git a/testdata/bd/strmxor_au6d.oas b/testdata/bd/strmxor_au6d.oas new file mode 100644 index 0000000000000000000000000000000000000000..2b90eba605162f66effed2900f71099ac85e40b1 GIT binary patch literal 498 zcmY!lcJ=kt^>+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>Fh}?YF|&pQIr;@NgV?+bqV{YIj7%T6 zFR*rU{$%B5SimO0%P9DQVIdng!v|3z!OR7045HQ`H5XV Date: Sat, 7 Sep 2019 22:30:10 +0200 Subject: [PATCH 3/3] First implementation of deep mode for XOR tool. --- .../tools/xor/lay_plugin/XORToolDialog.ui | 204 ++++++++++-------- .../tools/xor/lay_plugin/layXORToolDialog.cc | 164 +++++++++++++- .../tools/xor/lay_plugin/layXORToolDialog.h | 1 + 3 files changed, 270 insertions(+), 99 deletions(-) diff --git a/src/plugins/tools/xor/lay_plugin/XORToolDialog.ui b/src/plugins/tools/xor/lay_plugin/XORToolDialog.ui index e9cf1d978..b9ad1d6c8 100644 --- a/src/plugins/tools/xor/lay_plugin/XORToolDialog.ui +++ b/src/plugins/tools/xor/lay_plugin/XORToolDialog.ui @@ -231,19 +231,78 @@ - - - - - 0 - 0 - - + + - A XOR B (differences) + Tolerances (t1,t2,..) in micron - - true + + + + + + Threads + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + + + + + + 1 + 0 + + + + Used for tiles and layers + + + + + + + + + + Tolerances + + + + + + + Compare modes @@ -263,6 +322,22 @@ + + + + + 0 + 0 + + + + A XOR B (differences) + + + true + + + @@ -273,42 +348,27 @@ - - - - Tolerances + + + + + 0 + 0 + - - - - - Compare modes - - - - - - - Tolerances (t1,t2,..) in micron + B NOT A (in B but not in A) - - - Threads - - - - Tiling - + QFrame::NoFrame @@ -365,66 +425,6 @@ - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 1 - - - - - - - - 1 - 0 - - - - Used for tiles and layers - - - - - - - - - - - 0 - 0 - - - - B NOT A (in B but not in A) - - - @@ -435,6 +435,20 @@ + + + + Hierarchical + + + + + + + consider hierarchy (experimental) + + + diff --git a/src/plugins/tools/xor/lay_plugin/layXORToolDialog.cc b/src/plugins/tools/xor/lay_plugin/layXORToolDialog.cc index 61be73e10..9ab95e94f 100644 --- a/src/plugins/tools/xor/lay_plugin/layXORToolDialog.cc +++ b/src/plugins/tools/xor/lay_plugin/layXORToolDialog.cc @@ -25,11 +25,13 @@ #include "layXORProgress.h" #include "antService.h" #include "rdb.h" +#include "rdbUtils.h" #include "dbShapeProcessor.h" #include "dbRecursiveShapeIterator.h" #include "dbClip.h" #include "dbLayoutUtils.h" #include "dbRegion.h" +#include "dbDeepShapeStore.h" #include "tlTimer.h" #include "tlProgress.h" #include "tlThreadedWorkers.h" @@ -58,6 +60,7 @@ std::string cfg_xor_anotb ("xor-anotb"); std::string cfg_xor_bnota ("xor-bnota"); std::string cfg_xor_summarize ("xor-summarize"); std::string cfg_xor_tolerances ("xor-tolerances"); +std::string cfg_xor_deep ("xor-deep"); std::string cfg_xor_tiling ("xor-tiling"); std::string cfg_xor_tiling_heal ("xor-tiling-heal"); std::string cfg_xor_region_mode ("xor-region-mode"); @@ -169,6 +172,7 @@ XORToolDialog::XORToolDialog (QWidget *parent) connect (mp_ui->input_layers_cbx, SIGNAL (currentIndexChanged (int)), this, SLOT (input_changed (int))); connect (mp_ui->output_cbx, SIGNAL (currentIndexChanged (int)), this, SLOT (output_changed (int))); + connect (mp_ui->deep, SIGNAL (clicked ()), this, SLOT (deep_changed ())); input_changed (0); output_changed (0); @@ -251,6 +255,12 @@ XORToolDialog::exec_dialog (lay::LayoutView *view) mp_ui->tolerances->setText (tl::to_qstring (tol)); } + bool deep = false; + if (config_root->config_get (cfg_xor_deep, deep)) { + mp_ui->deep->setChecked (deep); + } + deep_changed (); + std::string tiling; if (config_root->config_get (cfg_xor_tiling, tiling)) { mp_ui->tiling->setText (tl::to_qstring (tiling)); @@ -335,6 +345,7 @@ BEGIN_PROTECTED config_root->config_set (cfg_xor_layer_offset, tl::to_string (mp_ui->layer_offset_le->text ())); config_root->config_set (cfg_xor_summarize, mp_ui->summarize_cb->isChecked ()); config_root->config_set (cfg_xor_tolerances, tl::to_string (mp_ui->tolerances->text ())); + config_root->config_set (cfg_xor_deep, mp_ui->deep->isChecked ()); config_root->config_set (cfg_xor_tiling, tl::to_string (mp_ui->tiling->text ())); config_root->config_set (cfg_xor_tiling_heal, mp_ui->heal_cb->isChecked ()); config_root->config_end (); @@ -344,6 +355,14 @@ BEGIN_PROTECTED END_PROTECTED } +void +XORToolDialog::deep_changed () +{ + bool deep = mp_ui->deep->isChecked (); + mp_ui->tiling->setEnabled (!deep); + mp_ui->heal_cb->setEnabled (!deep); +} + void XORToolDialog::input_changed (int /*index*/) { @@ -510,6 +529,28 @@ public: } } + void issue_region (unsigned int tol_index, unsigned int layer_index, const db::Region ®ion) + { + QMutexLocker locker (&m_mutex); + db::CplxTrans trans (dbu ()); + + if (m_output_mode == OMMarkerDatabase) { + + rdb::Category *layercat = m_layer_categories[tol_index][layer_index]; + + std::pair it = region.begin_iter (); + rdb::scan_layer (layercat, m_rdb_cell, trans * it.second, it.first, false); + + } else { + + db::Cell *output_cell = m_sub_cells[tol_index]; + unsigned int output_layer = m_sub_output_layers[tol_index][layer_index]; + + region.insert_into (output_cell->layout (), output_cell->cell_index (), output_layer); + + } + } + void issue_polygon (unsigned int tol_index, unsigned int layer_index, const db::Polygon &polygon, bool touches_border = false) { QMutexLocker locker (&m_mutex); @@ -588,12 +629,17 @@ class XORTask : public tl::Task { public: - XORTask (const std::string &tile_desc, const db::Box &clip_box, const db::Box ®ion_a, const db::Box ®ion_b, unsigned int layer_index, const db::LayerProperties &lp, const std::vector &la, const std::vector &lb, int ix, int iy) - : m_tile_desc (tile_desc), m_clip_box (clip_box), m_region_a (region_a), m_region_b (region_b), m_layer_index (layer_index), m_lp (lp), m_la (la), m_lb (lb), m_ix (ix), m_iy (iy) + XORTask (bool deep, const std::string &tile_desc, const db::Box &clip_box, const db::Box ®ion_a, const db::Box ®ion_b, unsigned int layer_index, const db::LayerProperties &lp, const std::vector &la, const std::vector &lb, int ix, int iy) + : m_deep (deep), m_tile_desc (tile_desc), m_clip_box (clip_box), m_region_a (region_a), m_region_b (region_b), m_layer_index (layer_index), m_lp (lp), m_la (la), m_lb (lb), m_ix (ix), m_iy (iy) { // .. nothing yet .. } + bool deep () const + { + return m_deep; + } + const std::string &tile_desc () const { return m_tile_desc; @@ -645,6 +691,7 @@ public: } private: + bool m_deep; std::string m_tile_desc; db::Box m_clip_box, m_region_a, m_region_b; unsigned int m_layer_index; @@ -675,10 +722,117 @@ private: XORJob *mp_job; void do_perform (const XORTask *task); + void do_perform_tiled (const XORTask *task); + void do_perform_deep (const XORTask *task); }; void XORWorker::do_perform (const XORTask *xor_task) +{ + if (xor_task->deep ()) { + do_perform_deep (xor_task); + } else { + do_perform_tiled (xor_task); + } +} + +void +XORWorker::do_perform_deep (const XORTask *xor_task) +{ + db::DeepShapeStore dss; + db::Region rr; + + unsigned int tol_index = 0; + for (std::vector ::const_iterator t = mp_job->tolerances ().begin (); t != mp_job->tolerances ().end (); ++t, ++tol_index) { + + const std::vector &la = xor_task->la (); + const std::vector &lb = xor_task->lb (); + + if ((!la.empty () && !lb.empty ()) || mp_job->el_handling () != XORJob::EL_summarize) { + + if (tl::verbosity () >= 10) { + tl::info << "XOR tool (hierarchical): layer " << xor_task->lp ().to_string () << ", tolerance " << *t * mp_job->dbu (); + } + + tl::SelfTimer timer (tl::verbosity () >= 11, "Elapsed time"); + + if (tol_index == 0) { + + if ((!la.empty () && !lb.empty ()) || mp_job->el_handling () == XORJob::EL_process) { + + tl::SelfTimer timer (tl::verbosity () >= 21, "Boolean part"); + + db::RecursiveShapeIterator s_a (mp_job->cva ()->layout (), mp_job->cva ()->layout ().cell (mp_job->cva ().cell_index ()), la, xor_task->region_a ()); + db::RecursiveShapeIterator s_b (mp_job->cvb ()->layout (), mp_job->cvb ()->layout ().cell (mp_job->cvb ().cell_index ()), lb, xor_task->region_b ()); + + db::Region ra (s_a, dss, db::ICplxTrans (mp_job->cva ()->layout ().dbu () / mp_job->dbu ())); + db::Region rb (s_b, dss, db::ICplxTrans (mp_job->cvb ()->layout ().dbu () / mp_job->dbu ())); + + if (mp_job->op () == db::BooleanOp::Xor) { + rr = ra ^ rb; + } else if (mp_job->op () == db::BooleanOp::ANotB) { + rr = ra - rb; + } else if (mp_job->op () == db::BooleanOp::BNotA) { + rr = rb - ra; + } + + } else if (mp_job->op () == db::BooleanOp::Xor || + (mp_job->op () == db::BooleanOp::ANotB && !la.empty ()) || + (mp_job->op () == db::BooleanOp::BNotA && !lb.empty ())) { + + tl::SelfTimer timer (tl::verbosity () >= 21, "Boolean part (shortcut)"); + + db::RecursiveShapeIterator s; + db::ICplxTrans dbu_scale; + + if (!la.empty ()) { + s = db::RecursiveShapeIterator (mp_job->cva ()->layout (), *mp_job->cva ().cell (), la, xor_task->region_a ()); + dbu_scale = db::ICplxTrans (mp_job->cva ()->layout ().dbu () / mp_job->dbu ()); + } else if (!lb.empty ()) { + s = db::RecursiveShapeIterator (mp_job->cvb ()->layout (), *mp_job->cvb ().cell (), lb, xor_task->region_b ()); + dbu_scale = db::ICplxTrans (mp_job->cvb ()->layout ().dbu () / mp_job->dbu ()); + } + + rr = db::Region (s, dss, dbu_scale); + + } + + } + + if (*t > 0) { + tl::SelfTimer timer (tl::verbosity () >= 21, "Sizing part"); + rr.size (-((*t + 1) / 2), (unsigned int)2, false); + rr.size (((*t + 1) / 2), (unsigned int)2, false); + } + + // TODO: no clipping for hieararchical mode yet + mp_job->issue_region (tol_index, xor_task->layer_index (), rr); + + mp_job->add_results (xor_task->lp (), *t, rr.size (), xor_task->ix (), xor_task->iy ()); + + } else if (mp_job->op () == db::BooleanOp::Xor || + (mp_job->op () == db::BooleanOp::ANotB && !la.empty ()) || + (mp_job->op () == db::BooleanOp::BNotA && !lb.empty ())) { + + if (!la.empty ()) { + mp_job->issue_string (tol_index, xor_task->layer_index (), tl::to_string (QObject::tr ("Layer not present at all in layout B"))); + mp_job->add_results (xor_task->lp (), *t, missing_in_b, 0, 0); + } + + if (!lb.empty ()) { + mp_job->issue_string (tol_index, xor_task->layer_index (), tl::to_string (QObject::tr ("Layer not present at all in layout A"))); + mp_job->add_results (xor_task->lp (), *t, missing_in_a, 0, 0); + } + + } + + mp_job->next_progress (); + + } +} + +void +XORWorker::do_perform_tiled (const XORTask *xor_task) { db::ShapeProcessor sp (true); @@ -927,6 +1081,8 @@ XORToolDialog::run_xor () bool anotb = mp_ui->anotb_cb->isChecked (); bool bnota = mp_ui->bnota_cb->isChecked (); + bool deep = mp_ui->deep->isChecked (); + bool summarize = mp_ui->summarize_cb->isChecked (); // TODO: make this a user interface feature later bool process_el = lay::ApplicationBase::instance ()->special_app_flag ("ALWAYS_DO_XOR"); @@ -1018,7 +1174,7 @@ XORToolDialog::run_xor () double tile_size = 0; // in micron units bool tile_heal = mp_ui->heal_cb->isChecked (); - { + if (! deep) { std::string text (tl::to_string (mp_ui->tiling->text ())); tl::Extractor ex (text.c_str ()); double t = 0.0; @@ -1357,7 +1513,7 @@ XORToolDialog::run_xor () unsigned int layer_index = 0; for (std::map, std::vector >, db::LPLogicalLessFunc>::const_iterator l = layers.begin (); l != layers.end (); ++l, ++layer_index) { - job.schedule (new XORTask (tile_desc, clip_box, region_a, region_b, layer_index, l->first, l->second.first, l->second.second, int (nw), int (nh))); + job.schedule (new XORTask (deep, tile_desc, clip_box, region_a, region_b, layer_index, l->first, l->second.first, l->second.second, int (nw), int (nh))); } } diff --git a/src/plugins/tools/xor/lay_plugin/layXORToolDialog.h b/src/plugins/tools/xor/lay_plugin/layXORToolDialog.h index 65028d217..3f947c274 100644 --- a/src/plugins/tools/xor/lay_plugin/layXORToolDialog.h +++ b/src/plugins/tools/xor/lay_plugin/layXORToolDialog.h @@ -68,6 +68,7 @@ protected: void run_xor (); protected slots: + void deep_changed (); void input_changed (int index); void output_changed (int index);