mirror of https://github.com/KLayout/klayout.git
Fixed issue #1281 (Layout diff should ignore shape or instance duplicates)
A new option in the diff tool and strmcmp has been added (-1|--ignore-duplicates in strcmp). In RBA/pya, the "IgnoreDuplicates" flag has been added.
This commit is contained in:
parent
5bcb9e0207
commit
7f8eeb3a09
|
|
@ -41,6 +41,7 @@ BD_PUBLIC int strmcmp (int argc, char *argv[])
|
|||
std::string infile_a, infile_b;
|
||||
std::string top_a, top_b;
|
||||
bool silent = false;
|
||||
bool ignore_duplicates = false;
|
||||
bool no_text_orientation = true;
|
||||
bool no_text_details = true;
|
||||
bool no_properties = false;
|
||||
|
|
@ -106,6 +107,10 @@ BD_PUBLIC int strmcmp (int argc, char *argv[])
|
|||
<< tl::arg ("--expand-arrays", &flatten_array_insts, "Expands array instances before compare",
|
||||
"With this option, arrays are equivalent single instances are treated identical."
|
||||
)
|
||||
<< tl::arg ("-1|--ignore-duplicates", &ignore_duplicates, "Ignore duplicate instances and shapes",
|
||||
"With this option, duplicate instances or shapes are ignored and duplication "
|
||||
"does not count as a difference."
|
||||
)
|
||||
<< tl::arg ("-l|--layer-details", &dont_summarize_missing_layers, "Prints details about differences for missing layers",
|
||||
"With this option, missing layers are treated as \"empty\" and details about differences to "
|
||||
"other, non-empty layers are printed. Essentially the content of the non-empty counterpart "
|
||||
|
|
@ -155,6 +160,9 @@ BD_PUBLIC int strmcmp (int argc, char *argv[])
|
|||
if (silent) {
|
||||
flags |= db::layout_diff::f_silent;
|
||||
}
|
||||
if (ignore_duplicates) {
|
||||
flags |= db::layout_diff::f_ignore_duplicates;
|
||||
}
|
||||
if (no_text_orientation) {
|
||||
flags |= db::layout_diff::f_no_text_orientation;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,10 @@ collect_cells (const db::Layout &l, const db::Cell *top, std::map <std::string,
|
|||
}
|
||||
|
||||
static void
|
||||
collect_insts_of_unmapped_cells (const db::Layout & /*l*/, const db::Cell *cell, unsigned int /*flags*/, const std::map <db::cell_index_type, db::cell_index_type> &cci, std::vector <db::CellInstArrayWithProperties> &insts)
|
||||
collect_insts_of_unmapped_cells (const db::Layout & /*l*/, const db::Cell *cell, unsigned int /*flags*/, const std::map <db::cell_index_type, db::cell_index_type> &cci, std::vector <db::CellInstArrayWithProperties> &insts, bool no_duplicates)
|
||||
{
|
||||
size_t n_before = insts.size ();
|
||||
|
||||
for (db::Cell::const_iterator i = cell->begin (); !i.at_end (); ++i) {
|
||||
|
||||
std::map <db::cell_index_type, db::cell_index_type>::const_iterator ccii = cci.find (i->cell_index ());
|
||||
|
|
@ -81,6 +83,13 @@ collect_insts_of_unmapped_cells (const db::Layout & /*l*/, const db::Cell *cell,
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
if (no_duplicates) {
|
||||
|
||||
std::sort (insts.begin () + n_before, insts.end ());
|
||||
insts.erase (std::unique (insts.begin () + n_before, insts.end ()), insts.end ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -102,7 +111,7 @@ rewrite_instances_to (std::vector <db::CellInstArrayWithProperties> &insts, unsi
|
|||
}
|
||||
|
||||
static void
|
||||
collect_insts (const db::Layout & /*l*/, const db::Cell *cell, unsigned int flags, const std::map <db::cell_index_type, db::cell_index_type> &cci, std::vector <db::CellInstArrayWithProperties> &insts, PropertyMapper &pn)
|
||||
collect_insts (const db::Layout & /*l*/, const db::Cell *cell, unsigned int flags, const std::map <db::cell_index_type, db::cell_index_type> &cci, std::vector <db::CellInstArrayWithProperties> &insts, PropertyMapper &pn, bool no_duplicates)
|
||||
{
|
||||
insts.clear ();
|
||||
|
||||
|
|
@ -148,6 +157,10 @@ collect_insts (const db::Layout & /*l*/, const db::Cell *cell, unsigned int flag
|
|||
}
|
||||
|
||||
std::sort (insts.begin (), insts.end ());
|
||||
|
||||
if (no_duplicates) {
|
||||
insts.erase (std::unique (insts.begin (), insts.end ()), insts.end ());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -178,10 +191,10 @@ int compare_seq (I b1, I e1, I b2, I e2, Op op)
|
|||
/**
|
||||
* @brief Reduces two vectors to the common objects as determined by the compare operator
|
||||
* If the iterate parameter is true, the reduction is repeated until no more reduction can be
|
||||
* achieved. This is useful with tolerances since the sorted is not strict in that case.
|
||||
* achieved. This is useful with tolerances since the sorting is not strict in that case.
|
||||
*/
|
||||
template <class X, class Op>
|
||||
void reduce (std::vector<X> &a, std::vector<X> &b, Op op, bool iterate)
|
||||
void reduce (std::vector<X> &a, std::vector<X> &b, Op op, bool iterate, bool no_duplicates)
|
||||
{
|
||||
do {
|
||||
|
||||
|
|
@ -196,12 +209,29 @@ void reduce (std::vector<X> &a, std::vector<X> &b, Op op, bool iterate)
|
|||
|
||||
while (ra != a.end () && rb != b.end ()) {
|
||||
if (op (*ra, *rb)) {
|
||||
*wa++ = *ra++;
|
||||
typename std::vector<X>::const_iterator r = ra++;
|
||||
*wa = *r;
|
||||
while (no_duplicates && ra != a.end () && !op (*ra, *r) && !op(*r, *ra)) {
|
||||
++ra;
|
||||
}
|
||||
++wa;
|
||||
} else if (op (*rb, *ra)) {
|
||||
*wb++ = *rb++;
|
||||
typename std::vector<X>::const_iterator r = rb++;
|
||||
*wb = *r;
|
||||
while (no_duplicates && rb != b.end () && !op (*rb, *r) && !op(*r, *rb)) {
|
||||
++rb;
|
||||
}
|
||||
++wb;
|
||||
} else {
|
||||
++ra;
|
||||
++rb;
|
||||
typename std::vector<X>::const_iterator r;
|
||||
r = ra++;
|
||||
while (no_duplicates && ra != a.end () && !op (*ra, *r) && !op(*r, *ra)) {
|
||||
++ra;
|
||||
}
|
||||
r = rb++;
|
||||
while (no_duplicates && rb != b.end () && !op (*rb, *r) && !op(*r, *rb)) {
|
||||
++rb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,14 +241,22 @@ void reduce (std::vector<X> &a, std::vector<X> &b, Op op, bool iterate)
|
|||
|
||||
if (ra != wa) {
|
||||
while (ra != a.end ()) {
|
||||
*wa++ = *ra++;
|
||||
typename std::vector<X>::const_iterator r = ra++;
|
||||
*wa++ = *r;
|
||||
while (no_duplicates && ra != a.end () && !op (*ra, *r) && !op(*r, *ra)) {
|
||||
++ra;
|
||||
}
|
||||
}
|
||||
a.erase (wa, a.end ());
|
||||
}
|
||||
|
||||
if (rb != wb) {
|
||||
while (rb != b.end ()) {
|
||||
*wb++ = *rb++;
|
||||
typename std::vector<X>::const_iterator r = rb++;
|
||||
*wb++ = *r;
|
||||
while (no_duplicates && rb != b.end () && !op (*rb, *r) && !op(*r, *rb)) {
|
||||
++rb;
|
||||
}
|
||||
}
|
||||
b.erase (wb, b.end ());
|
||||
}
|
||||
|
|
@ -405,7 +443,7 @@ struct PolygonCompareOpWithTolerance
|
|||
m_eb.push_back (*e);
|
||||
}
|
||||
|
||||
reduce (m_ea, m_eb, EdgeCompareOpWithTolerance (m_tolerance), m_tolerance > 0);
|
||||
reduce (m_ea, m_eb, EdgeCompareOpWithTolerance (m_tolerance), m_tolerance > 0, false);
|
||||
|
||||
return compare_seq (m_ea.begin (), m_ea.end (), m_eb.begin (), m_eb.end (), EdgeCompareOpWithTolerance (m_tolerance)) < 0;
|
||||
}
|
||||
|
|
@ -665,6 +703,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
}
|
||||
|
||||
bool verbose = (flags & layout_diff::f_verbose);
|
||||
bool no_duplicates = (flags & layout_diff::f_ignore_duplicates);
|
||||
|
||||
db::Layout n, na, nb;
|
||||
na.properties_repository () = a.properties_repository ();
|
||||
|
|
@ -897,20 +936,20 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
r.bbox_differs (cell_a->bbox (), cell_b->bbox ());
|
||||
}
|
||||
|
||||
collect_insts (a, cell_a, flags, common_cell_indices_a, insts_a, prop_normalize_a);
|
||||
collect_insts (b, cell_b, flags, common_cell_indices_b, insts_b, prop_normalize_b);
|
||||
collect_insts (a, cell_a, flags, common_cell_indices_a, insts_a, prop_normalize_a, no_duplicates);
|
||||
collect_insts (b, cell_b, flags, common_cell_indices_b, insts_b, prop_normalize_b, no_duplicates);
|
||||
|
||||
std::vector <db::CellInstArrayWithProperties> anotb;
|
||||
std::set_difference (insts_a.begin (), insts_a.end (), insts_b.begin (), insts_b.end (), std::back_inserter (anotb));
|
||||
|
||||
rewrite_instances_to (anotb, flags, common_cells_a, prop_remap_to_a);
|
||||
collect_insts_of_unmapped_cells (a, cell_a, flags, common_cell_indices_a, anotb);
|
||||
collect_insts_of_unmapped_cells (a, cell_a, flags, common_cell_indices_a, anotb, no_duplicates);
|
||||
|
||||
std::vector <db::CellInstArrayWithProperties> bnota;
|
||||
std::set_difference (insts_b.begin (), insts_b.end (), insts_a.begin (), insts_a.end (), std::back_inserter (bnota));
|
||||
|
||||
rewrite_instances_to (bnota, flags, common_cells_b, prop_remap_to_b);
|
||||
collect_insts_of_unmapped_cells (b, cell_b, flags, common_cell_indices_b, bnota);
|
||||
collect_insts_of_unmapped_cells (b, cell_b, flags, common_cell_indices_b, bnota, no_duplicates);
|
||||
|
||||
if (! anotb.empty () || ! bnota.empty ()) {
|
||||
|
||||
|
|
@ -979,7 +1018,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
collect_polygons (b, cell_b, layer_b, flags, polygons_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (polygons_a, polygons_b, make_polygon_compare_func (tolerance), tolerance > 0);
|
||||
reduce (polygons_a, polygons_b, make_polygon_compare_func (tolerance), tolerance > 0, no_duplicates);
|
||||
|
||||
if (!polygons_a.empty () || !polygons_b.empty ()) {
|
||||
differs = true;
|
||||
|
|
@ -1007,7 +1046,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
collect_paths (b, cell_b, layer_b, flags, paths_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (paths_a, paths_b, make_path_compare_func (tolerance), tolerance > 0);
|
||||
reduce (paths_a, paths_b, make_path_compare_func (tolerance), tolerance > 0, no_duplicates);
|
||||
|
||||
if (!paths_a.empty () || !paths_b.empty ()) {
|
||||
differs = true;
|
||||
|
|
@ -1034,7 +1073,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
collect_texts (b, cell_b, layer_b, flags, texts_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (texts_a, texts_b, make_text_compare_func (tolerance), tolerance > 0);
|
||||
reduce (texts_a, texts_b, make_text_compare_func (tolerance), tolerance > 0, no_duplicates);
|
||||
|
||||
if (!texts_a.empty () || !texts_b.empty ()) {
|
||||
differs = true;
|
||||
|
|
@ -1061,7 +1100,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
collect_boxes (b, cell_b, layer_b, flags, boxes_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (boxes_a, boxes_b, make_box_compare_func (tolerance), tolerance > 0);
|
||||
reduce (boxes_a, boxes_b, make_box_compare_func (tolerance), tolerance > 0, no_duplicates);
|
||||
|
||||
if (!boxes_a.empty () || !boxes_b.empty ()) {
|
||||
differs = true;
|
||||
|
|
@ -1088,7 +1127,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
collect_edges (b, cell_b, layer_b, flags, edges_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (edges_a, edges_b, make_edge_compare_func (tolerance), tolerance > 0);
|
||||
reduce (edges_a, edges_b, make_edge_compare_func (tolerance), tolerance > 0, no_duplicates);
|
||||
|
||||
if (!edges_a.empty () || !edges_b.empty ()) {
|
||||
differs = true;
|
||||
|
|
@ -1113,7 +1152,7 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
collect_edge_pairs (b, cell_b, layer_b, flags, edge_pairs_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (edge_pairs_a, edge_pairs_b, make_edge_pair_compare_func (tolerance), tolerance > 0);
|
||||
reduce (edge_pairs_a, edge_pairs_b, make_edge_pair_compare_func (tolerance), tolerance > 0, no_duplicates);
|
||||
|
||||
if (!edge_pairs_a.empty () || !edge_pairs_b.empty ()) {
|
||||
differs = true;
|
||||
|
|
|
|||
|
|
@ -74,12 +74,15 @@ const unsigned int f_paths_as_polygons = 0x100;
|
|||
// Derive smart cell mapping instead of name mapping (available only if top cells are specified)
|
||||
const unsigned int f_smart_cell_mapping = 0x200;
|
||||
|
||||
// Don't summarize missing layers
|
||||
// Don't summarize missing layers - print them in detail
|
||||
const unsigned int f_dont_summarize_missing_layers = 0x400;
|
||||
|
||||
// Ignore text details (font, size, presentation)
|
||||
const unsigned int f_no_text_details = 0x800;
|
||||
|
||||
// Ignore duplicate instances or shapes
|
||||
const unsigned int f_ignore_duplicates = 0x1000;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ TestDifferenceReceiver::print_cell_inst (const db::CellInstArrayWithProperties &
|
|||
}
|
||||
if (ci.properties_id () != 0) {
|
||||
m_os << " [" << ci.properties_id () << "]" << std::endl;
|
||||
} else {
|
||||
m_os << "" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -489,7 +491,9 @@ TEST(1)
|
|||
" c4 m45 *1 -10,20\n"
|
||||
" c4 m45 *1 -10,20\n"
|
||||
"Not in b but in a:\n"
|
||||
" c5x r0 *1 10,-20 c5x m45 *1 -10,20Not in a but in b:\n"
|
||||
" c5x r0 *1 10,-20\n"
|
||||
" c5x m45 *1 -10,20\n"
|
||||
"Not in a but in b:\n"
|
||||
);
|
||||
|
||||
g = h;
|
||||
|
|
@ -951,7 +955,7 @@ TEST(3)
|
|||
c2h.shapes (0).insert (db::Polygon (db::Box (1, 2, 1003, 1006)));
|
||||
|
||||
r.clear ();
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 0, r);
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 0, r);
|
||||
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
|
|
@ -965,7 +969,7 @@ TEST(3)
|
|||
);
|
||||
|
||||
r.clear ();
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, r);
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, r);
|
||||
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
|
|
@ -1499,4 +1503,205 @@ TEST(7)
|
|||
EXPECT_EQ (r.text (), "");
|
||||
}
|
||||
|
||||
TEST(8)
|
||||
{
|
||||
db::Layout g;
|
||||
g.insert_layer (0);
|
||||
g.set_properties (0, db::LayerProperties (17, 0));
|
||||
g.insert_layer (1);
|
||||
g.set_properties (1, db::LayerProperties (42, 1));
|
||||
|
||||
db::cell_index_type c1i = g.add_cell ("c1");
|
||||
db::cell_index_type c2i = g.add_cell ("c2x");
|
||||
db::cell_index_type c3i = g.add_cell ("c3");
|
||||
db::cell_index_type c4i = g.add_cell ("c4");
|
||||
db::cell_index_type c5i = g.add_cell ("c5x");
|
||||
|
||||
{
|
||||
|
||||
db::Cell &c1 (g.cell (c1i));
|
||||
db::Cell &c2 (g.cell (c2i));
|
||||
db::Cell &c3 (g.cell (c3i));
|
||||
db::Cell &c4 (g.cell (c4i));
|
||||
db::Cell &c5 (g.cell (c5i));
|
||||
c2.shapes (0).insert (db::Box (0, 1, 2, 3));
|
||||
|
||||
db::FTrans f (1, true);
|
||||
db::Vector p (-10, 20);
|
||||
db::Trans t (f.rot (), p);
|
||||
db::Vector pp (10, -20);
|
||||
db::Trans tt (0, pp);
|
||||
|
||||
// c4->c1 (aref)
|
||||
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
|
||||
// c5->c1
|
||||
c5.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
|
||||
// c3->c5 (3x)
|
||||
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
|
||||
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
|
||||
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
|
||||
// c4->c3
|
||||
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c3.cell_index ()), t));
|
||||
// c4->c1
|
||||
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
|
||||
// c2->c1 (2x)
|
||||
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
|
||||
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
|
||||
// c2->c4 (2x)
|
||||
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
|
||||
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
|
||||
|
||||
}
|
||||
|
||||
db::Layout h = g;
|
||||
|
||||
TestDifferenceReceiver r;
|
||||
bool eq;
|
||||
|
||||
g.cell (c2i).shapes (0).insert (db::Box (1, 2, 1001, 1002));
|
||||
g.cell (c2i).shapes (0).insert (db::Box (2, 3, 1002, 1003));
|
||||
g.cell (c2i).shapes (0).insert (db::Box (2, 3, 1002, 1003));
|
||||
g.cell (c2i).shapes (0).insert (db::Box (3, 4, 1003, 1004));
|
||||
g.cell (c2i).shapes (0).insert (db::Box (3, 4, 1003, 1004));
|
||||
|
||||
h.cell (c2i).shapes (0).insert (db::Box (1, 2, 1001, 1002));
|
||||
h.cell (c2i).shapes (0).insert (db::Box (1, 2, 1001, 1002));
|
||||
h.cell (c2i).shapes (0).insert (db::Box (2, 3, 1002, 1003));
|
||||
h.cell (c2i).shapes (0).insert (db::Box (4, 5, 1004, 1005));
|
||||
h.cell (c2i).shapes (0).insert (db::Box (4, 5, 1004, 1005));
|
||||
|
||||
r.clear ();
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 0, r);
|
||||
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
"layout_diff: boxes differ for layer 17/0 in cell c2x\n"
|
||||
"Not in b but in a:\n"
|
||||
" (2,3;1002,1003)\n"
|
||||
" (3,4;1003,1004)\n"
|
||||
" (3,4;1003,1004)\n"
|
||||
"Not in a but in b:\n"
|
||||
" (1,2;1001,1002)\n"
|
||||
" (4,5;1004,1005)\n"
|
||||
" (4,5;1004,1005)\n"
|
||||
);
|
||||
|
||||
r.clear ();
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose + db::layout_diff::f_ignore_duplicates, 0, r);
|
||||
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
"layout_diff: boxes differ for layer 17/0 in cell c2x\n"
|
||||
"Not in b but in a:\n"
|
||||
" (3,4;1003,1004)\n"
|
||||
"Not in a but in b:\n"
|
||||
" (4,5;1004,1005)\n"
|
||||
);
|
||||
|
||||
// duplicate instances
|
||||
{
|
||||
db::FTrans f (1, true);
|
||||
db::Vector p (-10, 20);
|
||||
db::Trans t (f.rot (), p);
|
||||
|
||||
h.cell(c4i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1i), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
|
||||
h.cell(c4i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1i), t));
|
||||
h.cell(c4i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1i), t));
|
||||
|
||||
g.cell(c5i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1i), t));
|
||||
g.cell(c5i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1i), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
|
||||
g.cell(c5i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1i), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
|
||||
|
||||
db::cell_index_type c6i = g.add_cell ("c6");
|
||||
g.cell(c5i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c6i), t));
|
||||
g.cell(c5i).insert (db::array <db::CellInst, db::Trans> (db::CellInst (c6i), t));
|
||||
|
||||
}
|
||||
|
||||
r.clear ();
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 0, r);
|
||||
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
"layout_diff: cell c6 is not present in layout b, but in a\n"
|
||||
"layout_diff: boxes differ for layer 17/0 in cell c2x\n"
|
||||
"Not in b but in a:\n"
|
||||
" (2,3;1002,1003)\n"
|
||||
" (3,4;1003,1004)\n"
|
||||
" (3,4;1003,1004)\n"
|
||||
"Not in a but in b:\n"
|
||||
" (1,2;1001,1002)\n"
|
||||
" (4,5;1004,1005)\n"
|
||||
" (4,5;1004,1005)\n"
|
||||
"layout_diff: instances differ in cell c4\n"
|
||||
"list for a:\n"
|
||||
" c1 r0 *1 10,-20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c3 m45 *1 -10,20\n"
|
||||
"list for b:\n"
|
||||
" c1 r0 *1 10,-20\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c3 m45 *1 -10,20\n"
|
||||
"Not in b but in a:\n"
|
||||
"Not in a but in b:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
"layout_diff: instances differ in cell c5x\n"
|
||||
"list for a:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
"list for b:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
"Not in b but in a:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c6 m45 *1 -10,20\n"
|
||||
" c6 m45 *1 -10,20\n"
|
||||
"Not in a but in b:\n"
|
||||
);
|
||||
|
||||
r.clear ();
|
||||
eq = db::compare_layouts (g, h, db::layout_diff::f_verbose + db::layout_diff::f_ignore_duplicates, 0, r);
|
||||
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
"layout_diff: cell c6 is not present in layout b, but in a\n"
|
||||
"layout_diff: boxes differ for layer 17/0 in cell c2x\n"
|
||||
"Not in b but in a:\n"
|
||||
" (3,4;1003,1004)\n"
|
||||
"Not in a but in b:\n"
|
||||
" (4,5;1004,1005)\n"
|
||||
"layout_diff: instances differ in cell c4\n"
|
||||
"list for a:\n"
|
||||
" c1 r0 *1 10,-20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c3 m45 *1 -10,20\n"
|
||||
"list for b:\n"
|
||||
" c1 r0 *1 10,-20\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c3 m45 *1 -10,20\n"
|
||||
"Not in b but in a:\n"
|
||||
"Not in a but in b:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
"layout_diff: instances differ in cell c5x\n"
|
||||
"list for a:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
"list for b:\n"
|
||||
" c1 m45 *1 -10,20\n"
|
||||
"Not in b but in a:\n"
|
||||
" c1 m45 *1 -10,20[a=1,1, b=0,2, na=2, nb=3]\n"
|
||||
" c6 m45 *1 -10,20\n"
|
||||
"Not in a but in b:\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,76 +1,73 @@
|
|||
<ui version="4.0" >
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DiffToolDialog</class>
|
||||
<widget class="QDialog" name="DiffToolDialog" >
|
||||
<property name="geometry" >
|
||||
<widget class="QDialog" name="DiffToolDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>498</width>
|
||||
<width>503</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<property name="windowTitle">
|
||||
<string>Diff Tool</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Input</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin" stdset="0">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Layout A </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Layout B</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layouta" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<item row="0" column="1">
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layouta">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy" >
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layoutb" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<item row="1" column="1">
|
||||
<widget class="lay::CellViewSelectionComboBox" name="layoutb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy" >
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
@ -79,77 +76,84 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="smart_cbx" >
|
||||
<property name="text" >
|
||||
<widget class="QCheckBox" name="smart_cbx">
|
||||
<property name="text">
|
||||
<string>Don't use names to match cells (use geometrical properties)</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="xor_cbx" >
|
||||
<property name="text" >
|
||||
<widget class="QCheckBox" name="xor_cbx">
|
||||
<property name="text">
|
||||
<string>Run XOR on differences</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="summarize_cbx" >
|
||||
<property name="text" >
|
||||
<widget class="QCheckBox" name="summarize_cbx">
|
||||
<property name="text">
|
||||
<string>Summarize missing layers</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="detailed_cbx" >
|
||||
<property name="text" >
|
||||
<widget class="QCheckBox" name="detailed_cbx">
|
||||
<property name="text">
|
||||
<string>Detailed information</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="expand_cell_arrays_cbx" >
|
||||
<property name="text" >
|
||||
<widget class="QCheckBox" name="expand_cell_arrays_cbx">
|
||||
<property name="text">
|
||||
<string>Expand cell arrays (compare single instance by instance)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exact_cbx" >
|
||||
<property name="text" >
|
||||
<widget class="QCheckBox" name="exact_cbx">
|
||||
<property name="text">
|
||||
<string>Exact compare (includes properties, text orientation and similar)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ignore_duplicates_cbx">
|
||||
<property name="text">
|
||||
<string>Ignore duplicate instances and shapes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>472</width>
|
||||
<height>16</height>
|
||||
|
|
@ -158,12 +162,12 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -187,11 +191,11 @@
|
|||
<receiver>DiffToolDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
|
|
@ -203,11 +207,11 @@
|
|||
<receiver>DiffToolDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ std::string cfg_diff_smart ("diff-smart");
|
|||
std::string cfg_diff_summarize ("diff-summarize");
|
||||
std::string cfg_diff_expand_cell_arrays ("diff-expand-cell-arrays");
|
||||
std::string cfg_diff_exact ("diff-exact");
|
||||
std::string cfg_diff_ignore_duplicates ("diff-ignore-duplicates");
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// RdbDifferenceReceiver definition
|
||||
|
|
@ -650,6 +651,9 @@ DiffToolDialog::exec_dialog (lay::LayoutViewBase *view)
|
|||
if (config_root->config_get (cfg_diff_exact, f)) {
|
||||
mp_ui->exact_cbx->setChecked (f);
|
||||
}
|
||||
if (config_root->config_get (cfg_diff_ignore_duplicates, f)) {
|
||||
mp_ui->ignore_duplicates_cbx->setChecked (f);
|
||||
}
|
||||
|
||||
update ();
|
||||
|
||||
|
|
@ -686,6 +690,7 @@ BEGIN_PROTECTED
|
|||
config_root->config_set (cfg_diff_summarize, mp_ui->summarize_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_expand_cell_arrays, mp_ui->expand_cell_arrays_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_exact, mp_ui->exact_cbx->isChecked ());
|
||||
config_root->config_set (cfg_diff_ignore_duplicates, mp_ui->ignore_duplicates_cbx->isChecked ());
|
||||
config_root->config_end ();
|
||||
|
||||
QDialog::accept ();
|
||||
|
|
@ -712,6 +717,7 @@ DiffToolDialog::run_diff ()
|
|||
bool summarize = !run_xor && mp_ui->summarize_cbx->isChecked ();
|
||||
bool expand_cell_arrays = !run_xor && mp_ui->expand_cell_arrays_cbx->isChecked ();
|
||||
bool exact = !run_xor && mp_ui->exact_cbx->isChecked ();
|
||||
bool ignore_duplicates = mp_ui->ignore_duplicates_cbx->isChecked ();
|
||||
|
||||
int cv_index_a = mp_ui->layouta->current_cv_index ();
|
||||
int cv_index_b = mp_ui->layoutb->current_cv_index ();
|
||||
|
|
@ -740,6 +746,9 @@ DiffToolDialog::run_diff ()
|
|||
if (smart) {
|
||||
flags |= db::layout_diff::f_smart_cell_mapping;
|
||||
}
|
||||
if (ignore_duplicates) {
|
||||
flags |= db::layout_diff::f_ignore_duplicates;
|
||||
}
|
||||
|
||||
// TODO: make an parameter
|
||||
db::Coord tolerance = 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue