2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
KLayout Layout Viewer
|
|
|
|
|
Copyright (C) 2006-2021 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 "dbRecursiveInstanceIterator.h"
|
|
|
|
|
#include "dbRegion.h"
|
|
|
|
|
#include "dbLayoutDiff.h"
|
|
|
|
|
#include "tlString.h"
|
|
|
|
|
#include "tlUnitTest.h"
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
std::string collect(db::RecursiveInstanceIterator &s, const db::Layout &layout)
|
|
|
|
|
{
|
|
|
|
|
std::string res;
|
|
|
|
|
while (! s.at_end ()) {
|
|
|
|
|
if (! res.empty ()) {
|
|
|
|
|
res += "/";
|
|
|
|
|
}
|
|
|
|
|
if (s.cell ()) {
|
|
|
|
|
res += std::string ("[") + layout.cell_name (s.cell ()->cell_index ()) + "]";
|
|
|
|
|
} else {
|
|
|
|
|
res += "[]";
|
|
|
|
|
}
|
2021-02-20 22:17:43 +01:00
|
|
|
res += s->inst_ptr.to_string (true);
|
2021-02-20 00:40:05 +01:00
|
|
|
++s;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string collect_with_copy(db::RecursiveInstanceIterator s, const db::Layout &layout)
|
|
|
|
|
{
|
|
|
|
|
s.reset ();
|
|
|
|
|
return collect (s, layout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(1)
|
|
|
|
|
{
|
|
|
|
|
db::Manager m (true);
|
|
|
|
|
db::Layout g (&m);
|
|
|
|
|
g.insert_layer (0);
|
|
|
|
|
g.insert_layer (1);
|
|
|
|
|
g.insert_layer (2);
|
|
|
|
|
|
|
|
|
|
db::Cell &c0 (g.cell (g.add_cell ()));
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator idef;
|
|
|
|
|
EXPECT_EQ (idef.at_end (), true);
|
|
|
|
|
EXPECT_EQ (collect (idef, g), "");
|
|
|
|
|
EXPECT_EQ (collect_with_copy (idef, g), "");
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i00 (g, c0, db::Box (0, 0, 100, 100));
|
|
|
|
|
EXPECT_EQ (collect (i00, g), "");
|
|
|
|
|
EXPECT_EQ (collect_with_copy (i00, g), "");
|
|
|
|
|
|
|
|
|
|
db::Cell &c1 (g.cell (g.add_cell ()));
|
|
|
|
|
db::Cell &c2 (g.cell (g.add_cell ()));
|
|
|
|
|
db::Cell &c3 (g.cell (g.add_cell ()));
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i0 (g, c0, db::Box (0, 0, 100, 100));
|
|
|
|
|
EXPECT_EQ (collect (i0, g), "");
|
|
|
|
|
EXPECT_EQ (collect_with_copy (i0, g), "");
|
|
|
|
|
|
|
|
|
|
db::Box b (0, 100, 1000, 1200);
|
|
|
|
|
c0.shapes (0).insert (b);
|
|
|
|
|
c1.shapes (0).insert (b);
|
|
|
|
|
c2.shapes (0).insert (b);
|
|
|
|
|
c3.shapes (0).insert (b);
|
|
|
|
|
|
|
|
|
|
c0.shapes (2).insert (b);
|
|
|
|
|
c0.shapes (2).insert (b.moved (db::Vector (50, 50)));
|
|
|
|
|
|
|
|
|
|
db::Trans tt;
|
|
|
|
|
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt));
|
|
|
|
|
c0.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), db::Trans (db::Vector (100, -100))));
|
|
|
|
|
c0.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (1)));
|
|
|
|
|
c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (db::Vector (1100, 0))));
|
|
|
|
|
|
|
|
|
|
std::string x;
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i1 (g, c0, db::Box (0, 0, 100, 100));
|
|
|
|
|
x = collect(i1, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
x = collect_with_copy(i1, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i1_1inf (g, c0, db::Box (0, 0, 100, 100));
|
2021-02-20 00:48:07 +01:00
|
|
|
i1_1inf.min_depth(0);
|
2021-02-20 00:40:05 +01:00
|
|
|
x = collect(i1_1inf, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
x = collect_with_copy(i1_1inf, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
|
2021-02-20 00:48:07 +01:00
|
|
|
db::RecursiveInstanceIterator i1_11 (g, c0, db::Box (0, 0, 2000, 100));
|
|
|
|
|
i1_11.min_depth(0);
|
|
|
|
|
i1_11.max_depth(0);
|
2021-02-20 00:40:05 +01:00
|
|
|
x = collect(i1_11, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
x = collect_with_copy(i1_11, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
|
2021-02-20 00:48:07 +01:00
|
|
|
db::RecursiveInstanceIterator i1_12 (g, c0, db::Box (0, 0, 2000, 100));
|
|
|
|
|
i1_12.min_depth(0);
|
|
|
|
|
i1_12.max_depth(1);
|
2021-02-20 00:40:05 +01:00
|
|
|
x = collect(i1_12, g);
|
2021-02-20 00:48:07 +01:00
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
2021-02-20 00:40:05 +01:00
|
|
|
x = collect_with_copy(i1_12, g);
|
2021-02-20 00:48:07 +01:00
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 22:17:43 +01:00
|
|
|
db::RecursiveInstanceIterator i1_22 (g, c0, db::Box (0, 0, 2000, 100));
|
2021-02-20 00:48:07 +01:00
|
|
|
i1_22.min_depth(1);
|
|
|
|
|
i1_22.max_depth(1);
|
2021-02-20 00:40:05 +01:00
|
|
|
x = collect(i1_22, g);
|
2021-02-20 22:17:43 +01:00
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
2021-02-20 00:40:05 +01:00
|
|
|
x = collect_with_copy(i1_22, g);
|
2021-02-20 22:17:43 +01:00
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i1o (g, c0, db::Box (0, 0, 100, 100), true);
|
|
|
|
|
x = collect(i1o, g);
|
|
|
|
|
EXPECT_EQ (x, "");
|
|
|
|
|
x = collect_with_copy(i1o, g);
|
|
|
|
|
EXPECT_EQ (x, "");
|
|
|
|
|
i1o = db::RecursiveInstanceIterator (g, c0, db::Box (0, 0, 100, 101), true);
|
|
|
|
|
x = collect(i1o, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0");
|
|
|
|
|
x = collect_with_copy(i1o, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0");
|
|
|
|
|
i1o = db::RecursiveInstanceIterator (g, c0, db::Box (0, 0, 101, 101), true);
|
|
|
|
|
x = collect(i1o, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
x = collect_with_copy(i1o, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i2 (g, c0, db::Box (-100, 0, 100, 100));
|
|
|
|
|
db::RecursiveInstanceIterator i2c = i2;
|
|
|
|
|
x = collect(i2, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i2, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect(i2c, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i2c, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
db::RecursiveInstanceIterator i2o (g, c0, db::Box (-100, 0, 100, 100), true);
|
|
|
|
|
x = collect(i2o, g);
|
|
|
|
|
EXPECT_EQ (x, "");
|
|
|
|
|
x = collect_with_copy(i2o, g);
|
|
|
|
|
EXPECT_EQ (x, "");
|
|
|
|
|
i2o = db::RecursiveInstanceIterator (g, c0, db::Box (-101, 0, 101, 101), true);
|
|
|
|
|
x = collect(i2o, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i2o, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Region r;
|
|
|
|
|
r.insert (db::Box (-600, -100, -500, 0));
|
|
|
|
|
r.insert (db::Box (1600, 0, 1700, 100));
|
|
|
|
|
db::RecursiveInstanceIterator i2r (g, c0, r);
|
|
|
|
|
db::RecursiveInstanceIterator i2rc = i2r;
|
|
|
|
|
x = collect(i2r, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i2r, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect(i2rc, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i2rc, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
db::RecursiveInstanceIterator i2ro (g, c0, r, true);
|
|
|
|
|
x = collect(i2ro, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
|
|
|
|
x = collect_with_copy(i2ro, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$3 r0 100,-100");
|
|
|
|
|
|
2021-02-20 00:40:05 +01:00
|
|
|
db::RecursiveInstanceIterator i4 (g, c0, db::Box (-100, 0, 2000, 100));
|
|
|
|
|
db::RecursiveInstanceIterator i4_copy (g, c0, db::Box (-100, 0, 2000, 100));
|
|
|
|
|
i4.max_depth (0);
|
|
|
|
|
x = collect(i4, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i4, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (i4 == i4, true);
|
|
|
|
|
EXPECT_EQ (i4 != i4, false);
|
|
|
|
|
EXPECT_EQ (i4 == i4_copy, false);
|
|
|
|
|
EXPECT_EQ (i4 != i4_copy, true);
|
|
|
|
|
i4 = i4_copy;
|
|
|
|
|
EXPECT_EQ (i4 == i4_copy, true);
|
|
|
|
|
EXPECT_EQ (i4 != i4_copy, false);
|
|
|
|
|
i4.max_depth (1);
|
|
|
|
|
x = collect(i4, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i4, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
|
|
|
|
i4 = i4_copy;
|
|
|
|
|
x = collect(i4, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i4, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
|
|
|
|
db::RecursiveInstanceIterator i5 (g, c0, db::Box::world ());
|
|
|
|
|
x = collect(i5, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i5, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
|
|
|
|
std::set<db::cell_index_type> cc;
|
|
|
|
|
db::RecursiveInstanceIterator ii;
|
|
|
|
|
|
|
|
|
|
ii = db::RecursiveInstanceIterator (g, c0, db::Box::world ());
|
|
|
|
|
cc.clear ();
|
|
|
|
|
cc.insert (c2.cell_index ());
|
|
|
|
|
ii.unselect_all_cells ();
|
|
|
|
|
ii.select_cells (cc);
|
|
|
|
|
x = collect(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
|
|
|
|
x = collect_with_copy(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
|
|
|
|
ii.reset ();
|
|
|
|
|
x = collect(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
|
|
|
|
x = collect_with_copy(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
|
|
|
|
|
|
|
|
|
ii.reset_selection ();
|
|
|
|
|
x = collect(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$3]$4 r0 1100,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
|
|
|
|
ii.reset_selection ();
|
|
|
|
|
cc.clear ();
|
|
|
|
|
cc.insert (c0.cell_index ());
|
|
|
|
|
cc.insert (c2.cell_index ());
|
|
|
|
|
ii.unselect_cells (cc);
|
|
|
|
|
cc.clear ();
|
|
|
|
|
cc.insert (c2.cell_index ());
|
|
|
|
|
ii.select_cells (cc);
|
|
|
|
|
x = collect(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
|
|
|
|
x = collect_with_copy(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0");
|
|
|
|
|
|
|
|
|
|
ii = db::RecursiveInstanceIterator (g, c0, db::Box::world ());
|
|
|
|
|
ii.unselect_all_cells ();
|
|
|
|
|
cc.clear ();
|
|
|
|
|
cc.insert (c0.cell_index ());
|
|
|
|
|
ii.select_cells (cc);
|
|
|
|
|
x = collect(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(ii, g);
|
|
|
|
|
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100/[$1]$4 r90 0,0");
|
|
|
|
|
|
2021-02-20 01:09:17 +01:00
|
|
|
db::RecursiveInstanceIterator i1z (g, c0);
|
2021-02-20 17:50:32 +01:00
|
|
|
EXPECT_EQ (i1z.all_targets_enabled (), true);
|
2021-02-20 01:09:17 +01:00
|
|
|
std::set<db::cell_index_type> ct;
|
|
|
|
|
ct.insert (c3.cell_index ());
|
2021-02-20 17:50:32 +01:00
|
|
|
i1z.set_targets (ct);
|
|
|
|
|
EXPECT_EQ (i1z.all_targets_enabled (), false);
|
2021-02-20 01:09:17 +01:00
|
|
|
EXPECT_EQ (i1z.targets () == ct, true);
|
2021-02-20 17:50:32 +01:00
|
|
|
i1z.enable_all_targets ();
|
|
|
|
|
EXPECT_EQ (i1z.all_targets_enabled (), true);
|
2021-02-20 01:09:17 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
i1z.set_targets (ct);
|
|
|
|
|
EXPECT_EQ (i1z.all_targets_enabled (), false);
|
2021-02-20 01:09:17 +01:00
|
|
|
|
|
|
|
|
x = collect(i1z, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$4 r90 0,0");
|
|
|
|
|
x = collect_with_copy(i1z, g);
|
|
|
|
|
EXPECT_EQ (x, "[$3]$4 r0 1100,0/[$1]$4 r90 0,0");
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static db::Layout boxes2layout (const std::set<db::Box> &boxes)
|
|
|
|
|
{
|
|
|
|
|
db::Layout l;
|
|
|
|
|
l.insert_layer(0, db::LayerProperties (1, 0));
|
|
|
|
|
db::Cell &top (l.cell (l.add_cell ()));
|
|
|
|
|
|
|
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
top.shapes (0).insert (*b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return l;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-21 22:11:33 +01:00
|
|
|
namespace {
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-21 22:11:33 +01:00
|
|
|
class FlatPusher
|
|
|
|
|
: public db::RecursiveInstanceReceiver
|
2021-02-20 00:40:05 +01:00
|
|
|
{
|
2021-02-21 22:11:33 +01:00
|
|
|
public:
|
|
|
|
|
FlatPusher (std::set<db::Box> *boxes) : mp_boxes (boxes) { }
|
|
|
|
|
|
|
|
|
|
void enter_cell (const db::RecursiveInstanceIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
|
|
|
|
{
|
|
|
|
|
mp_boxes->insert (iter->trans () * cell->bbox ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::set<db::Box> *mp_boxes;
|
|
|
|
|
};
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-21 22:11:33 +01:00
|
|
|
}
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
TEST(2)
|
2021-02-20 00:40:05 +01:00
|
|
|
{
|
2021-02-20 17:50:32 +01:00
|
|
|
// Big fun with cells
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
db::Manager m (true);
|
|
|
|
|
db::Layout g (&m);
|
|
|
|
|
g.insert_layer(0);
|
|
|
|
|
|
|
|
|
|
db::Cell &c0 (g.cell (g.add_cell ()));
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Cell &c1 (g.cell (g.add_cell ()));
|
|
|
|
|
|
|
|
|
|
db::Box basic_box (0, 0, 10, 10);
|
|
|
|
|
c1.shapes (0).insert (basic_box);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
std::set<db::Box> boxes;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 100000; ++i) {
|
|
|
|
|
|
|
|
|
|
int x = rand () % 10000;
|
|
|
|
|
int y = rand () % 10000;
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
boxes.insert (basic_box.moved (db::Vector (x, y)));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y))));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db::Box search_box (2500, 2500, 7500, 7500);
|
|
|
|
|
|
|
|
|
|
std::set<db::Box> selected_boxes;
|
|
|
|
|
std::set<db::Box> selected_boxes2;
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true); !iter.at_end (); ++iter) {
|
2021-02-20 22:17:43 +01:00
|
|
|
selected_boxes.insert (iter.trans () * iter->inst_ptr.bbox ());
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
if (search_box.overlaps (*b)) {
|
|
|
|
|
selected_boxes2.insert (*b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
// push mode
|
|
|
|
|
{
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
FlatPusher pusher (&selected_boxes);
|
2021-02-20 17:50:32 +01:00
|
|
|
db::RecursiveInstanceIterator (g, c0, search_box, true).push (&pusher);
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
db::Box search_box2 (500, 500, 1000, 1000);
|
|
|
|
|
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
selected_boxes2.clear ();
|
|
|
|
|
|
|
|
|
|
db::Region reg;
|
|
|
|
|
reg.insert (search_box);
|
|
|
|
|
reg.insert (search_box2);
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) {
|
2021-02-20 22:17:43 +01:00
|
|
|
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
if (search_box.overlaps (*b) || search_box2.overlaps (*b)) {
|
|
|
|
|
selected_boxes2.insert (*b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
// push mode
|
|
|
|
|
{
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
FlatPusher pusher (&selected_boxes);
|
2021-02-20 17:50:32 +01:00
|
|
|
db::RecursiveInstanceIterator (g, c0, reg, true).push (&pusher);
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
TEST(3)
|
2021-02-20 00:40:05 +01:00
|
|
|
{
|
2021-02-20 17:50:32 +01:00
|
|
|
// Big fun with cells - 2 hierarchy levels
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
db::Manager m (true);
|
|
|
|
|
db::Layout g (&m);
|
|
|
|
|
g.insert_layer(0);
|
|
|
|
|
|
|
|
|
|
db::Cell &c0 (g.cell (g.add_cell ()));
|
|
|
|
|
db::Cell &c1 (g.cell (g.add_cell ()));
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Cell &c2 (g.cell (g.add_cell ()));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
db::Box basic_box (0, 0, 10, 10);
|
2021-02-20 17:50:32 +01:00
|
|
|
c2.shapes (0).insert (basic_box);
|
|
|
|
|
c1.insert (db::CellInstArray (c2.cell_index (), db::Trans (db::Vector (1, -1))));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
std::set<db::Box> boxes;
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
int nboxes = 100000;
|
|
|
|
|
for (int i = 0; i < nboxes; ++i) {
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
int x, y;
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
do {
|
|
|
|
|
x = rand () % 10000;
|
|
|
|
|
y = rand () % 10000;
|
|
|
|
|
} while (boxes.find (basic_box.moved (db::Vector (x + 1, y - 1))) != boxes.end ());
|
|
|
|
|
|
|
|
|
|
boxes.insert (basic_box.moved (db::Vector (x + 1, y - 1)));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y))));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db::Box search_box (2500, 2500, 7500, 7500);
|
|
|
|
|
|
|
|
|
|
std::set<db::Box> selected_boxes;
|
|
|
|
|
std::set<db::Box> selected_boxes2;
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box, true);
|
|
|
|
|
std::set<db::cell_index_type> tc;
|
|
|
|
|
tc.insert (c2.cell_index ());
|
|
|
|
|
iter.set_targets (tc);
|
|
|
|
|
int n = 0;
|
|
|
|
|
for ( ; !iter.at_end (); ++iter) {
|
|
|
|
|
++n;
|
2021-02-20 22:17:43 +01:00
|
|
|
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
int nn = 0;
|
2021-02-20 00:40:05 +01:00
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
if (search_box.overlaps (*b)) {
|
2021-02-20 17:50:32 +01:00
|
|
|
++nn;
|
2021-02-20 00:40:05 +01:00
|
|
|
selected_boxes2.insert (*b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
EXPECT_EQ (n, nn);
|
|
|
|
|
|
2021-02-20 00:40:05 +01:00
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
// push mode
|
|
|
|
|
{
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
FlatPusher pusher (&selected_boxes);
|
2021-02-20 17:50:32 +01:00
|
|
|
db::RecursiveInstanceIterator (g, c0, search_box, true).push (&pusher);
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
db::Box search_box2 (500, 500, 1000, 1000);
|
|
|
|
|
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
selected_boxes2.clear ();
|
|
|
|
|
|
|
|
|
|
db::Region reg;
|
|
|
|
|
reg.insert (search_box);
|
|
|
|
|
reg.insert (search_box2);
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg, true); !iter.at_end (); ++iter) {
|
2021-02-20 22:17:43 +01:00
|
|
|
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
if (search_box.overlaps (*b) || search_box2.overlaps (*b)) {
|
|
|
|
|
selected_boxes2.insert (*b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
// push mode
|
|
|
|
|
{
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
FlatPusher pusher (&selected_boxes);
|
2021-02-20 17:50:32 +01:00
|
|
|
db::RecursiveInstanceIterator (g, c0, reg, true).push (&pusher);
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
TEST(4)
|
2021-02-20 00:40:05 +01:00
|
|
|
{
|
2021-02-20 17:50:32 +01:00
|
|
|
// Big fun with cells - 2 hierarchy levels + touching mode
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Manager m (true);
|
|
|
|
|
db::Layout g (&m);
|
|
|
|
|
g.insert_layer(0);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Cell &c0 (g.cell (g.add_cell ()));
|
|
|
|
|
db::Cell &c1 (g.cell (g.add_cell ()));
|
|
|
|
|
db::Cell &c2 (g.cell (g.add_cell ()));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Box basic_box (0, 0, 10, 10);
|
|
|
|
|
c2.shapes (0).insert (basic_box);
|
|
|
|
|
c1.insert (db::CellInstArray (c2.cell_index (), db::Trans (db::Vector (1, -1))));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
std::set<db::Box> boxes;
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
int nboxes = 100000;
|
|
|
|
|
for (int i = 0; i < nboxes; ++i) {
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
int x, y;
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
do {
|
|
|
|
|
x = rand () % 10000;
|
|
|
|
|
y = rand () % 10000;
|
|
|
|
|
} while (boxes.find (basic_box.moved (db::Vector (x + 1, y - 1))) != boxes.end ());
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
boxes.insert (basic_box.moved (db::Vector (x + 1, y - 1)));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), db::Trans (db::Vector (x, y))));
|
2021-02-20 00:40:05 +01:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Box search_box (2500, 2500, 7500, 7500);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
std::set<db::Box> selected_boxes;
|
|
|
|
|
std::set<db::Box> selected_boxes2;
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, search_box);
|
|
|
|
|
std::set<db::cell_index_type> tc;
|
|
|
|
|
tc.insert (c2.cell_index ());
|
|
|
|
|
iter.set_targets (tc);
|
|
|
|
|
int n = 0;
|
|
|
|
|
for ( ; !iter.at_end (); ++iter) {
|
|
|
|
|
++n;
|
2021-02-20 22:17:43 +01:00
|
|
|
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
int nn = 0;
|
|
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
if (search_box.touches (*b)) {
|
|
|
|
|
++nn;
|
|
|
|
|
selected_boxes2.insert (*b);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
EXPECT_EQ (n, nn);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
// push mode
|
2021-02-20 00:40:05 +01:00
|
|
|
{
|
2021-02-20 17:50:32 +01:00
|
|
|
selected_boxes.clear ();
|
|
|
|
|
FlatPusher pusher (&selected_boxes);
|
|
|
|
|
db::RecursiveInstanceIterator (g, c0, search_box).push (&pusher);
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Box search_box2 (500, 500, 1000, 1000);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
selected_boxes.clear ();
|
|
|
|
|
selected_boxes2.clear ();
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
db::Region reg;
|
|
|
|
|
reg.insert (search_box);
|
|
|
|
|
reg.insert (search_box2);
|
2021-02-20 00:40:05 +01:00
|
|
|
|
2021-02-20 17:50:32 +01:00
|
|
|
for (db::RecursiveInstanceIterator iter = db::RecursiveInstanceIterator (g, c0, reg); !iter.at_end (); ++iter) {
|
2021-02-20 22:17:43 +01:00
|
|
|
selected_boxes.insert (iter.trans () * iter->bbox (db::box_convert<db::CellInst> (g)));
|
2021-02-20 17:50:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (std::set<db::Box>::const_iterator b = boxes.begin (); b != boxes.end (); ++b) {
|
|
|
|
|
if (search_box.touches (*b) || search_box2.touches (*b)) {
|
|
|
|
|
selected_boxes2.insert (*b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
|
|
|
|
|
|
|
|
|
// push mode
|
|
|
|
|
{
|
|
|
|
|
selected_boxes.clear ();
|
|
|
|
|
FlatPusher pusher (&selected_boxes);
|
|
|
|
|
db::RecursiveInstanceIterator (g, c0, reg).push (&pusher);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ (selected_boxes.size () > 100, true);
|
|
|
|
|
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
2021-02-20 00:40:05 +01:00
|
|
|
}
|
2021-02-20 17:50:32 +01:00
|
|
|
|