/* KLayout Layout Viewer Copyright (C) 2006-2017 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "utHead.h" #include "dbLayoutDiff.h" #include "dbLayerProperties.h" #include "dbLayout.h" #include class TestDifferenceReceiver : public db::DifferenceReceiver { public: TestDifferenceReceiver (); virtual ~TestDifferenceReceiver () { } std::string text () const { return m_os.str (); } void clear () { m_os.str (std::string ()); } void dbu_differs (double dbu_a, double dbu_b); void layer_in_a_only (const db::LayerProperties &la); void layer_in_b_only (const db::LayerProperties &lb); void layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb); void cell_in_a_only (const std::string &cellname, db::cell_index_type ci); void cell_in_b_only (const std::string &cellname, db::cell_index_type ci); void cell_name_differs (const std::string &cellname_a, db::cell_index_type cia, const std::string &cellname_b, db::cell_index_type cib); void begin_cell (const std::string &cellname, db::cell_index_type cia, db::cell_index_type cib); void bbox_differs (const db::Box &ba, const db::Box &bb); void begin_inst_differences (); void instances_in_a (const std::vector &insts_a, const std::vector &cell_names, const db::PropertiesRepository &props); void instances_in_b (const std::vector &insts_b, const std::vector &cell_names, const db::PropertiesRepository &props); void instances_in_a_only (const std::vector &anotb, const db::Layout &a); void instances_in_b_only (const std::vector &bnota, const db::Layout &b); void end_inst_differences (); void begin_layer (const db::LayerProperties &layer, unsigned int layer_index_a, bool is_valid_a, unsigned int layer_index_b, bool is_valid_b); void per_layer_bbox_differs (const db::Box &ba, const db::Box &bb); void begin_polygon_differences (); void detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b); void end_polygon_differences (); void begin_path_differences (); void detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b); void end_path_differences (); void begin_box_differences (); void detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b); void end_box_differences (); void begin_edge_differences (); void detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b); void end_edge_differences (); void begin_text_differences (); void detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b); void end_text_differences (); void end_layer (); void end_cell (); private: std::string m_cellname; std::ostringstream m_os; db::LayerProperties m_layer; void print_cell_inst (const db::CellInstArrayWithProperties &ci, const std::vector &cell_names); void print_cell_inst (const db::CellInstArrayWithProperties &ci, const db::Layout &l); template void print_diffs (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b); }; TestDifferenceReceiver::TestDifferenceReceiver () : m_cellname (), m_layer () { // .. nothing yet .. } void TestDifferenceReceiver::print_cell_inst (const db::CellInstArrayWithProperties &ci, const db::Layout &l) { m_os << " " << l.cell_name (ci.object ().cell_index ()) << " " << ci.complex_trans ().to_string (); db::Vector a, b; unsigned long amax, bmax; if (ci.is_regular_array (a, b, amax, bmax)) { m_os << "[a=" << a.to_string () << ", b=" << b.to_string () << ", na=" << amax << ", nb=" << bmax << "]"; } if (ci.properties_id () != 0) { m_os << " [" << ci.properties_id () << "]" << std::endl; } } void TestDifferenceReceiver::print_cell_inst (const db::CellInstArrayWithProperties &ci, const std::vector &cell_names) { m_os << " " << cell_names [ci.object ().cell_index ()] << " " << ci.complex_trans ().to_string (); db::Vector a, b; unsigned long amax, bmax; if (ci.is_regular_array (a, b, amax, bmax)) { m_os << "[a=" << a.to_string () << ", b=" << b.to_string () << ", na=" << amax << ", nb=" << bmax << "]"; } if (ci.properties_id () != 0) { m_os << " [" << ci.properties_id () << "]" << std::endl; } else { m_os << "" << std::endl; } } template void TestDifferenceReceiver::print_diffs (const db::PropertiesRepository & /*pr*/, const std::vector > &a, const std::vector > &b) { std::vector > anotb; std::set_difference (a.begin (), a.end (), b.begin (), b.end (), std::back_inserter (anotb)); for (typename std::vector >::const_iterator s = anotb.begin (); s != anotb.end (); ++s) { m_os << " " << s->first.to_string (); if (s->second != 0) { m_os << " [" << s->second << "]" << std::endl; } else { m_os << "" << std::endl; } } } void TestDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b) { m_os << "layout_diff: database units differ " << dbu_a << " vs. " << dbu_b << std::endl; } void TestDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la) { m_os << "layout_diff: layer " << la.to_string () << " is not present in layout b, but in a" << std::endl; } void TestDifferenceReceiver::layer_in_b_only (const db::LayerProperties &lb) { m_os << "layout_diff: layer " << lb.to_string () << " is not present in layout a, but in b" << std::endl; } void TestDifferenceReceiver::layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb) { m_os << "layout_diff: layer names differ between layout a and b for layer " << la.layer << "/" << la.datatype << ": " << la.name << " vs. " << lb.name << std::endl; } void TestDifferenceReceiver::cell_in_a_only (const std::string &cellname, db::cell_index_type /*ci*/) { m_os << "layout_diff: cell " << cellname << " is not present in layout b, but in a" << std::endl; } void TestDifferenceReceiver::cell_in_b_only (const std::string &cellname, db::cell_index_type /*ci*/) { m_os << "layout_diff: cell " << cellname << " is not present in layout a, but in b" << std::endl; } void TestDifferenceReceiver::cell_name_differs (const std::string &cellname_a, db::cell_index_type /*cia*/, const std::string &cellname_b, db::cell_index_type /*cib*/) { m_os << "layout_diff: cell " << cellname_a << " in a is renamed to " << cellname_b << " in b" << std::endl; } void TestDifferenceReceiver::bbox_differs (const db::Box &ba, const db::Box &bb) { m_os << "layout_diff: bounding boxes differ for cell " << m_cellname << ", " << ba.to_string () << " vs. " << bb.to_string () << std::endl; } void TestDifferenceReceiver::begin_cell (const std::string &cellname, db::cell_index_type /*cia*/, db::cell_index_type /*cib*/) { m_cellname = cellname; } void TestDifferenceReceiver::begin_inst_differences () { m_os << "layout_diff: instances differ in cell " << m_cellname << std::endl; } void TestDifferenceReceiver::instances_in_a (const std::vector &insts_a, const std::vector &cell_names, const db::PropertiesRepository & /*props*/) { m_os << "list for a:" << std::endl; for (std::vector ::const_iterator s = insts_a.begin (); s != insts_a.end (); ++s) { print_cell_inst (*s, cell_names); } } void TestDifferenceReceiver::instances_in_b (const std::vector &insts_b, const std::vector &cell_names, const db::PropertiesRepository & /*props*/) { m_os << "list for b:" << std::endl; for (std::vector ::const_iterator s = insts_b.begin (); s != insts_b.end (); ++s) { print_cell_inst (*s, cell_names); } } void TestDifferenceReceiver::instances_in_a_only (const std::vector &anotb, const db::Layout &a) { m_os << "Not in b but in a:" << std::endl; for (std::vector ::const_iterator s = anotb.begin (); s != anotb.end (); ++s) { print_cell_inst (*s, a); } } void TestDifferenceReceiver::instances_in_b_only (const std::vector &bnota, const db::Layout &b) { m_os << "Not in a but in b:" << std::endl; for (std::vector ::const_iterator s = bnota.begin (); s != bnota.end (); ++s) { print_cell_inst (*s, b); } } void TestDifferenceReceiver::end_inst_differences () { } void TestDifferenceReceiver::begin_layer (const db::LayerProperties &layer, unsigned int /*layer_index_a*/, bool /*is_valid_a*/, unsigned int /*layer_index_b*/, bool /*is_valid_b*/) { m_layer = layer; } void TestDifferenceReceiver::per_layer_bbox_differs (const db::Box &ba, const db::Box &bb) { m_os << "layout_diff: per-layer bounding boxes differ for cell " << m_cellname << ", layer (" << m_layer.to_string () << "), " << ba.to_string () << " vs. " << bb.to_string () << std::endl; } void TestDifferenceReceiver::begin_polygon_differences () { m_os << "layout_diff: polygons differ for layer " << m_layer.to_string () << " in cell " << m_cellname << std::endl; } void TestDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b) { m_os << "Not in b but in a:" << std::endl; print_diffs (pr, a, b); m_os << "Not in a but in b:" << std::endl; print_diffs (pr, b, a); } void TestDifferenceReceiver::end_polygon_differences () { } void TestDifferenceReceiver::begin_path_differences () { m_os << "layout_diff: paths differ for layer " << m_layer.to_string () << " in cell " << m_cellname << std::endl; } void TestDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b) { m_os << "Not in b but in a:" << std::endl; print_diffs (pr, a, b); m_os << "Not in a but in b:" << std::endl; print_diffs (pr, b, a); } void TestDifferenceReceiver::end_path_differences () { } void TestDifferenceReceiver::begin_box_differences () { m_os << "layout_diff: boxes differ for layer " << m_layer.to_string () << " in cell " << m_cellname << std::endl; } void TestDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b) { m_os << "Not in b but in a:" << std::endl; print_diffs (pr, a, b); m_os << "Not in a but in b:" << std::endl; print_diffs (pr, b, a); } void TestDifferenceReceiver::end_box_differences () { } void TestDifferenceReceiver::begin_edge_differences () { m_os << "layout_diff: edges differ for layer " << m_layer.to_string () << " in cell " << m_cellname << std::endl; } void TestDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b) { m_os << "Not in b but in a:" << std::endl; print_diffs (pr, a, b); m_os << "Not in a but in b:" << std::endl; print_diffs (pr, b, a); } void TestDifferenceReceiver::end_edge_differences () { } void TestDifferenceReceiver::begin_text_differences () { m_os << "layout_diff: texts differ for layer " << m_layer.to_string () << " in cell " << m_cellname << std::endl; } void TestDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector > &a, const std::vector > &b) { m_os << "Not in b but in a:" << std::endl; print_diffs (pr, a, b); m_os << "Not in a but in b:" << std::endl; print_diffs (pr, b, a); } void TestDifferenceReceiver::end_text_differences () { } void TestDifferenceReceiver::end_layer () { } void TestDifferenceReceiver::end_cell () { } TEST(1) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; TestDifferenceReceiver r; bool eq; r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, true); EXPECT_EQ (r.text (), ""); { // c2->c5 (2x) 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); g.cell (c2i).insert (db::array (db::CellInst (c5i), t)); g.cell (c2i).insert (db::array (db::CellInst (c5i), tt)); } r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: instances differ in cell c2x\n"); 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: instances differ in cell c2x\n" "list for a:\n" " c1 r0 *1 10,-20\n" " c1 m45 *1 -10,20\n" " c4 m45 *1 -10,20\n" " c4 m45 *1 -10,20\n" " c5x r0 *1 10,-20\n" " c5x m45 *1 -10,20\n" "list for b:\n" " c1 r0 *1 10,-20\n" " c1 m45 *1 -10,20\n" " 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" ); g = h; g.set_properties (1, db::LayerProperties (42, 2)); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: layer 42/2 is not present in layout b, but in a\n" "layout_diff: layer 42/1 is not present in layout a, but in b\n" ); g = h; g.rename_cell (c2i, "c2"); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: cell c2 is not present in layout b, but in a\n" "layout_diff: cell c2x is not present in layout a, but in b\n" ); } TEST(2) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; TestDifferenceReceiver r; bool eq; g.cell (c2i).shapes (0).insert (db::Box (1, 2, 1003, 1004)); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: bounding boxes differ for cell c2x, (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: per-layer bounding boxes differ for cell c2x, layer (17/0), (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: boxes differ for layer 17/0 in cell c2x\n" ); 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" " (1,2;1003,1004)\n" "Not in a but in b:\n" ); db::Layout hh = h; db::Cell &c2h = h.cell (c2i); c2h.shapes (0).insert (db::Box (1, 2, 1003, 1005)); c2h.shapes (0).insert (db::Box (2, 2, 1003, 1004)); c2h.shapes (0).insert (db::Box (1, 2, 1003, 1006)); 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" " (1,2;1003,1004)\n" "Not in a but in b:\n" " (1,2;1003,1005)\n" " (1,2;1003,1006)\n" " (2,2;1003,1004)\n" ); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, 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" "Not in a but in b:\n" " (2,2;1003,1004)\n" " (1,2;1003,1006)\n" ); } std::string ps2string (const db::PropertiesRepository &rep, db::properties_id_type pi) { std::string s; db::PropertiesRepository::properties_set ps = rep.properties (pi); for (db::PropertiesRepository::properties_set::const_iterator i = ps.begin (); i != ps.end (); ++i) { if (!s.empty ()) { s += ","; } s += rep.prop_name (i->first).to_string (); s += ":"; s += i->second.to_string (); } return s; } TEST(2P) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } { db::properties_id_type pi1, pi2, pi3; db::PropertiesRepository::properties_set ps; ps.insert (std::make_pair (g.properties_repository ().prop_name_id ("A"), tl::Variant (1))); pi1 = g.properties_repository ().properties_id (ps); EXPECT_EQ (pi1, 1); ps.clear (); ps.insert (std::make_pair (g.properties_repository ().prop_name_id ("B"), tl::Variant (2))); pi2 = g.properties_repository ().properties_id (ps); EXPECT_EQ (pi2, 2); ps.insert (std::make_pair (g.properties_repository ().prop_name_id ("C"), tl::Variant ("c"))); pi3 = g.properties_repository ().properties_id (ps); EXPECT_EQ (pi3, 3); EXPECT_EQ (ps2string (g.properties_repository (), 1), "A:1"); EXPECT_EQ (ps2string (g.properties_repository (), 2), "B:2"); EXPECT_EQ (ps2string (g.properties_repository (), 3), "B:2,C:c"); } db::Layout h = g; { EXPECT_EQ (ps2string (h.properties_repository (), 1), "A:1"); EXPECT_EQ (ps2string (h.properties_repository (), 2), "B:2"); EXPECT_EQ (ps2string (h.properties_repository (), 3), "B:2,C:c"); } TestDifferenceReceiver r; bool eq; g.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1004), 1)); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: bounding boxes differ for cell c2x, (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: per-layer bounding boxes differ for cell c2x, layer (17/0), (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: boxes differ for layer 17/0 in cell c2x\n" ); 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" " (1,2;1003,1004) [1]\n" "Not in a but in b:\n" ); db::Layout hh = h; // Note: properties are "normalized" (mapped to a common layout). In order to maintain // their meaning later, keep these inserts sorted by property ID: h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1006), 1)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1005), 2)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (2, 2, 1003, 1004), 3)); 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" " (1,2;1003,1004) [1]\n" "Not in a but in b:\n" " (1,2;1003,1006) [1]\n" " (1,2;1003,1005) [2]\n" " (2,2;1003,1004) [3]\n" ); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, 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" " (1,2;1003,1004) [1]\n" "Not in a but in b:\n" " (1,2;1003,1006) [1]\n" " (1,2;1003,1005) [2]\n" " (2,2;1003,1004) [3]\n" ); h = hh; { EXPECT_EQ (ps2string (h.properties_repository (), 1), "A:1"); EXPECT_EQ (ps2string (h.properties_repository (), 2), "B:2"); EXPECT_EQ (ps2string (h.properties_repository (), 3), "B:2,C:c"); } // Note: properties are "normalized" (mapped to a common layout). In order to maintain // their meaning later, keep these inserts sorted by property ID: h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1005), 1)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1006), 2)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (2, 2, 1003, 1004), 3)); 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" " (1,2;1003,1004) [1]\n" "Not in a but in b:\n" " (1,2;1003,1005) [1]\n" " (1,2;1003,1006) [2]\n" " (2,2;1003,1004) [3]\n" ); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, 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" "Not in a but in b:\n" " (1,2;1003,1006) [2]\n" " (2,2;1003,1004) [3]\n" ); h = hh; h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (2, 2, 1003, 1004), 1)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1006), 2)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1005), 3)); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, 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" "Not in a but in b:\n" " (1,2;1003,1006) [2]\n" " (1,2;1003,1005) [3]\n" ); h = hh; h.cell (c2i).shapes (0).insert (db::Box (2, 2, 1003, 1004)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1006), 1)); h.cell (c2i).shapes (0).insert (db::BoxWithProperties (db::Box (1, 2, 1003, 1005), 1)); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, 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" " (1,2;1003,1004) [1]\n" "Not in a but in b:\n" " (2,2;1003,1004)\n" " (1,2;1003,1006) [1]\n" " (1,2;1003,1005) [1]\n" ); } TEST(3) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; TestDifferenceReceiver r; bool eq; g.cell (c2i).shapes (0).insert (db::Polygon (db::Box (1, 2, 1003, 1004))); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: bounding boxes differ for cell c2x, (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: per-layer bounding boxes differ for cell c2x, layer (17/0), (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: polygons differ for layer 17/0 in cell c2x\n" ); 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: polygons differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" " (1,2;1,1004;1003,1004;1003,2)\n" "Not in a but in b:\n" ); db::Layout hh = h; db::Cell &c2h = h.cell (c2i); c2h.shapes (0).insert (db::Polygon (db::Box (1, 2, 1003, 1005))); c2h.shapes (0).insert (db::Polygon (db::Box (2, 2, 1003, 1004))); 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); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: polygons differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" " (1,2;1,1004;1003,1004;1003,2)\n" "Not in a but in b:\n" " (1,2;1,1005;1003,1005;1003,2)\n" " (1,2;1,1006;1003,1006;1003,2)\n" " (2,2;2,1004;1003,1004;1003,2)\n" ); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: polygons differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" "Not in a but in b:\n" " (2,2;2,1004;1003,1004;1003,2)\n" " (1,2;1,1006;1003,1006;1003,2)\n" ); } TEST(4) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; TestDifferenceReceiver r; bool eq; g.cell (c2i).shapes (0).insert (db::Edge (1, 2, 1003, 1004)); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: bounding boxes differ for cell c2x, (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: per-layer bounding boxes differ for cell c2x, layer (17/0), (0,1;1003,1004) vs. (0,1;2,3)\n" "layout_diff: edges differ for layer 17/0 in cell c2x\n" ); 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: edges differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" " (1,2;1003,1004)\n" "Not in a but in b:\n" ); db::Layout hh = h; db::Cell &c2h = h.cell (c2i); c2h.shapes (0).insert (db::Edge (1, 2, 1003, 1005)); c2h.shapes (0).insert (db::Edge (2, 2, 1003, 1004)); c2h.shapes (0).insert (db::Edge (1, 2, 1003, 1006)); 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: edges differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" " (1,2;1003,1004)\n" "Not in a but in b:\n" " (1,2;1003,1005)\n" " (1,2;1003,1006)\n" " (2,2;1003,1004)\n" ); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: edges differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" "Not in a but in b:\n" " (2,2;1003,1004)\n" " (1,2;1003,1006)\n" ); } TEST(5) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; TestDifferenceReceiver r; bool eq; db::Text t; t = db::Text ("X", db::Trans (1, db::Vector (2, 3)), 17); g.cell (c2i).shapes (0).insert (t); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: texts differ for layer 17/0 in cell c2x\n" ); 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: texts differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" " ('X',r90 2,3)\n" "Not in a but in b:\n" ); db::Layout hh = h; hh.cell (c2i).shapes (0).insert (t); r.clear (); eq = db::compare_layouts (g, hh, db::layout_diff::f_verbose, 0, r); EXPECT_EQ (eq, true); EXPECT_EQ (r.text (), ""); hh = h; db::Cell &c2h = h.cell (c2i); c2h.shapes (0).insert (db::Text ("Y", db::Trans (1, db::Vector (2, 3)), 17)); c2h.shapes (0).insert (db::Text ("X", db::Trans (2, db::Vector (2, 3)), 17)); c2h.shapes (0).insert (db::Text ("X", db::Trans (1, db::Vector (3, 4)), 17)); c2h.shapes (0).insert (db::Text ("X", db::Trans (1, db::Vector (2, 3)), 18)); // Text attributes like font and alignment are not compared, hence this text matches the one of g: c2h.shapes (0).insert (db::Text ("X", db::Trans (1, db::Vector (2, 3)), 17, db::DefaultFont, db::HAlignCenter, db::VAlignCenter)); 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: texts differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" "Not in a but in b:\n" " ('X',r90 3,4)\n" " ('X',r90 2,3)\n" " ('X',r180 2,3)\n" " ('Y',r90 2,3)\n" ); // two more to match more of h: g.cell (c2i).shapes (0).insert (t); g.cell (c2i).shapes (0).insert (t); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: texts differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" "Not in a but in b:\n" " ('X',r180 2,3)\n" " ('Y',r90 2,3)\n" ); } TEST(6) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; TestDifferenceReceiver r; bool eq; db::Point pts1[] = { db::Point (1, 2), db::Point (11, 12) }; db::Point pts2[] = { db::Point (1, 3), db::Point (11, 12) }; db::Point pts3[] = { db::Point (1, 3), db::Point (11, 11) }; db::Path p; p = db::Path (&pts1[0], &pts1[sizeof (pts1) / sizeof (pts1[0])], 17, 0, 0, false); g.cell (c2i).shapes (0).insert (p); r.clear (); eq = db::compare_layouts (g, h, 0, 0, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: bounding boxes differ for cell c2x, (-5,-4;17,18) vs. (0,1;2,3)\n" "layout_diff: per-layer bounding boxes differ for cell c2x, layer (17/0), (-5,-4;17,18) vs. (0,1;2,3)\n" "layout_diff: paths differ for layer 17/0 in cell c2x\n" ); 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: paths differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" " (1,2;11,12) w=17 bx=0 ex=0 r=false\n" "Not in a but in b:\n" ); db::Layout hh = h; hh.cell (c2i).shapes (0).insert (p); r.clear (); eq = db::compare_layouts (g, hh, db::layout_diff::f_verbose, 0, r); EXPECT_EQ (eq, true); EXPECT_EQ (r.text (), ""); hh = h; db::Cell &c2h = h.cell (c2i); c2h.shapes (0).insert (db::Path (&pts1[0], &pts1[sizeof (pts1) / sizeof (pts1[0])], 18, 0, 0, false)); c2h.shapes (0).insert (db::Path (&pts1[0], &pts1[sizeof (pts1) / sizeof (pts1[0])], 17, 1, 0, false)); c2h.shapes (0).insert (db::Path (&pts1[0], &pts1[sizeof (pts1) / sizeof (pts1[0])], 17, 0, -1, false)); c2h.shapes (0).insert (db::Path (&pts1[0], &pts1[sizeof (pts1) / sizeof (pts1[0])], 17, 0, 0, true)); c2h.shapes (0).insert (db::Path (&pts2[0], &pts2[sizeof (pts2) / sizeof (pts2[0])], 17, 0, 0, false)); c2h.shapes (0).insert (db::Path (&pts3[0], &pts3[sizeof (pts3) / sizeof (pts3[0])], 17, 0, 0, false)); 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: paths differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" "Not in a but in b:\n" " (1,2;11,12) w=17 bx=0 ex=-1 r=false\n" " (1,3;11,11) w=17 bx=0 ex=0 r=false\n" " (1,2;11,12) w=17 bx=0 ex=0 r=true\n" " (1,2;11,12) w=17 bx=1 ex=0 r=false\n" " (1,2;11,12) w=18 bx=0 ex=0 r=false\n" ); // two more to match more of h: g.cell (c2i).shapes (0).insert (p); g.cell (c2i).shapes (0).insert (p); g.cell (c2i).shapes (0).insert (p); g.cell (c2i).shapes (0).insert (p); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, r); EXPECT_EQ (eq, false); EXPECT_EQ (r.text (), "layout_diff: paths differ for layer 17/0 in cell c2x\n" "Not in b but in a:\n" "Not in a but in b:\n" " (1,2;11,12) w=17 bx=0 ex=0 r=true\n" ); } TEST(7) { 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 (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3)); // c5->c1 c5.insert (db::array (db::CellInst (c1.cell_index ()), t)); // c3->c5 (3x) c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); c3.insert (db::array (db::CellInst (c5.cell_index ()), tt)); c3.insert (db::array (db::CellInst (c5.cell_index ()), t)); // c4->c3 c4.insert (db::array (db::CellInst (c3.cell_index ()), t)); // c4->c1 c4.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c1 (2x) c2.insert (db::array (db::CellInst (c1.cell_index ()), t)); c2.insert (db::array (db::CellInst (c1.cell_index ()), tt)); // c2->c4 (2x) c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); c2.insert (db::array (db::CellInst (c4.cell_index ()), t)); } db::Layout h = g; db::Layout hh = g; db::Layout hhh = g; TestDifferenceReceiver r; bool eq; g.cell (c2i).shapes (0).insert (db::Box (1, 2, 1003, 1004)); g.cell (c2i).shapes (0).insert (db::Box (2, 3, 1004, 1005)); g.cell (c2i).shapes (0).insert (db::Box (3, 4, 1005, 1006)); g.cell (c2i).shapes (0).insert (db::Box (4, 5, 1006, 1007)); g.cell (c2i).shapes (0).insert (db::Box (5, 6, 1007, 1008)); g.cell (c2i).shapes (0).insert (db::Box (3, 7, 1008, 1009)); g.cell (c2i).shapes (0).insert (db::Box (3, 8, 1009, 1010)); h.cell (c2i).shapes (0).insert (db::Box (3, 8, 1009, 1010)); h.cell (c2i).shapes (0).insert (db::Box (3, 7, 1008, 1009)); h.cell (c2i).shapes (0).insert (db::Box (5, 6, 1007, 1008)); h.cell (c2i).shapes (0).insert (db::Box (4, 5, 1006, 1009)); h.cell (c2i).shapes (0).insert (db::Box (3, 4, 1005, 1006)); h.cell (c2i).shapes (0).insert (db::Box (2, 3, 1004, 1005)); h.cell (c2i).shapes (0).insert (db::Box (1, 2, 1003, 1004)); hh.cell (c2i).shapes (0).insert (db::Box (3, 8, 1009, 1010)); hh.cell (c2i).shapes (0).insert (db::Box (3, 7, 1008, 1009)); hh.cell (c2i).shapes (0).insert (db::Box (5, 6, 1007, 1008)); hh.cell (c2i).shapes (0).insert (db::Box (4, 5, 1006, 1007)); hh.cell (c2i).shapes (0).insert (db::Box (3, 4, 1005, 1006)); hh.cell (c2i).shapes (0).insert (db::Box (2, 3, 1004, 1005)); hh.cell (c2i).shapes (0).insert (db::Box (1, 2, 1003, 1004)); hhh.cell (c2i).shapes (0).insert (db::Box (3, 8, 1009, 1010)); hhh.cell (c2i).shapes (0).insert (db::Box (3, 7, 1008, 1009)); hhh.cell (c2i).shapes (0).insert (db::Box (5, 6, 1007, 1008)); hhh.cell (c2i).shapes (0).insert (db::Box (4, 5, 1006, 1008)); hhh.cell (c2i).shapes (0).insert (db::Box (3, 4, 1005, 1006)); hhh.cell (c2i).shapes (0).insert (db::Box (2, 3, 1004, 1005)); hhh.cell (c2i).shapes (0).insert (db::Box (1, 2, 1003, 1004)); 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" " (4,5;1006,1007)\n" "Not in a but in b:\n" " (4,5;1006,1009)\n" ); r.clear (); eq = db::compare_layouts (g, h, db::layout_diff::f_verbose, 1, 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" " (4,5;1006,1007)\n" "Not in a but in b:\n" " (4,5;1006,1009)\n" ); r.clear (); eq = db::compare_layouts (g, hh, db::layout_diff::f_verbose, 0, r); EXPECT_EQ (eq, true); EXPECT_EQ (r.text (), ""); r.clear (); eq = db::compare_layouts (g, hh, db::layout_diff::f_verbose, 1, r); EXPECT_EQ (eq, true); EXPECT_EQ (r.text (), ""); r.clear (); eq = db::compare_layouts (g, hhh, 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" " (4,5;1006,1007)\n" "Not in a but in b:\n" " (4,5;1006,1008)\n" ); r.clear (); eq = db::compare_layouts (g, hhh, db::layout_diff::f_verbose, 1, r); EXPECT_EQ (eq, true); EXPECT_EQ (r.text (), ""); }