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);