# encoding: UTF-8 # KLayout Layout Viewer # Copyright (C) 2006-2024 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 if !$:.member?(File::dirname($0)) $:.push(File::dirname($0)) end load("test_prologue.rb") class DBRecursiveShapeIterator_TestClass < TestBase def collect(s, l) # check native iteration here too .. res2 = [] s.each do |s| r = "[#{l.cell_name(s.cell_index)}]" if s.shape.is_box? box = s.shape.box r += box.transformed(s.trans).to_s else r += "X"; end res2.push(r) end res = [] s.reset while !s.at_end? r = "[#{l.cell_name(s.cell_index)}]" if s.shape.is_box? box = s.shape.box r += box.transformed(s.trans).to_s else r += "X"; end s.next res.push(r) end assert_equal(res, res2) return res.join("/") end def dcollect(s, l) res = [] while !s.at_end? r = "[#{l.cell_name(s.cell_index)}]" if s.shape.is_box? box = s.shape.dbox r += box.transformed(s.dtrans).to_s else r += "X"; end s.next res.push(r) end return res.join("/") end def acollect(s, l) res = [] while !s.at_end? r = "[#{l.cell_name(s.cell_index)}]" if s.shape.is_box? box = s.shape.box r += box.transformed(s.always_apply_trans).to_s else r += "X"; end s.next res.push(r) end return res.join("/") end def test_1 # Recursive shape iterator tests l = RBA::Layout.new l.insert_layer_at(0, RBA::LayerInfo.new(1, 0)) l.insert_layer_at(1, RBA::LayerInfo.new(2, 0)) c0 = l.cell(l.add_cell("c0")) c1 = l.cell(l.add_cell("c1")) c2 = l.cell(l.add_cell("c2")) c3 = l.cell(l.add_cell("c3")) b = RBA::Box.new(0, 100, 1000, 1200) c0.shapes(0).insert(b) c1.shapes(0).insert(b) c2.shapes(0).insert(b) c3.shapes(0).insert(b) bb = RBA::Box.new(1, 101, 1001, 1201) c3.shapes(1).insert(bb) tt = RBA::Trans.new c0.insert(RBA::CellInstArray.new(c1.cell_index, tt)) c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100)))) c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1))) c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0)))) i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100)) i1copy = i1.dup assert_equal(i1copy.overlapping?, false) assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)") i1.reset assert_equal(dcollect(i1, l), "[c0](0,0.1;1,1.2)/[c1](0,0.1;1,1.2)/[c2](0.1,0;1.1,1.1)") assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)") i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100)) assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)") i1 = c0.begin_shapes_rec_touching(0, RBA::Box.new(0, 0, 100, 100)) assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)") i1 = c0.begin_shapes_rec_touching(0, RBA::DBox.new(0, 0, 0.100, 0.100)) assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)") i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100)); assert_equal(collect(i1o, l), ""); i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100)); assert_equal(collect(i1o, l), ""); i1copy.overlapping = true assert_equal(i1copy.overlapping?, true) assert_equal(collect(i1copy, l), ""); i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 101)); assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)"); i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.101)); assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)"); i1copy.region = RBA::Box.new(0, 0, 100, 101) assert_equal(i1copy.region.to_s, "(0,0;100,101)") assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)"); i1copy.region = RBA::Region::new(RBA::Box.new(0, 0, 100, 101)) assert_equal(i1copy.region.to_s, "(0,0;100,101)") assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)"); i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101) i1copy.confine_region(RBA::Box.new(0, 0, 100, 101)) assert_equal(i1copy.region.to_s, "(0,0;100,101)") assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)"); i1copy.region = RBA::Box.new(-1000, -1000, 1100, 1101) i1copy.confine_region(RBA::Region::new(RBA::Box.new(0, 0, 100, 101))) assert_equal(i1copy.region.to_s, "(0,0;100,101)") assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)"); i1o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(0, 0, 101, 101)); assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)"); i1o = c0.begin_shapes_rec_overlapping(0, RBA::Box.new(0, 0, 101, 101)); assert_equal(collect(i1o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)"); i2 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 100, 100)); assert_equal(collect(i2, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)"); i2o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(-100, 0, 100, 100)); assert_equal(collect(i2o, l), ""); i2o = l.begin_shapes_overlapping(c0.cell_index, 0, RBA::Box.new(-101, 0, 101, 101)); assert_equal(collect(i2o, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)"); i4 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 2000, 100)); i4_copy = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(-100, 0, 2000, 100)); i4.max_depth = 0; assert_equal(collect(i4, l), "[c0](0,100;1000,1200)"); assert_equal(i4 == i4, true); assert_equal(i4 != i4, false); assert_equal(i4 == i4_copy, false); assert_equal(i4 != i4_copy, true); i4 = i4_copy.dup; assert_equal(i4 == i4_copy, true); assert_equal(i4 != i4_copy, false); i4.max_depth = 1; assert_equal(collect(i4, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](-1200,0;-100,1000)"); i4.assign(i4_copy); assert_equal(collect(i4, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)"); i5 = l.begin_shapes(c0.cell_index, 0); assert_equal(collect(i5, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)"); ii = RBA::RecursiveShapeIterator::new assert_equal(collect(ii, l), "") ii = RBA::RecursiveShapeIterator::new(l, c1, 0) assert_equal(collect(ii, l), "[c1](0,100;1000,1200)") assert_equal(ii.top_cell.name, "c1") assert_equal(ii.layout == l, true) ii.max_depth = 2 assert_equal(ii.max_depth, 2) ii.min_depth = 1 assert_equal(ii.min_depth, 1) ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1]) ic = ii.dup assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)") assert_equal(collect(ic, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)") ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 100), false) assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)") ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 100), true) assert_equal(collect(ii, l), "") ii = RBA::RecursiveShapeIterator::new(l, c2, 0, RBA::Box.new(-100, 0, 2000, 101), true) assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)") ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 100), false) assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)") ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 101), false) assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)/[c3](1101,101;2101,1201)") ii.reset assert_equal(acollect(ii, l), "[c2](0,100;1000,1200)/[c3](0,100;1000,1200)/[c3](1,101;1001,1201)") ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 20, 2000, 121), true) ii.global_trans = RBA::ICplxTrans::new(RBA::Vector::new(10, 20)) assert_equal(ii.global_trans.to_s, "r0 *1 10,20") assert_equal(collect(ii, l), "[c2](10,120;1010,1220)/[c3](1110,120;2110,1220)") ii.global_dtrans = RBA::DCplxTrans::new(RBA::DVector::new(0.01, 0.02)) ii.reset assert_equal(ii.global_dtrans.to_s, "r0 *1 0.01,0.02") assert_equal(collect(ii, l), "[c2](10,120;1010,1220)/[c3](1110,120;2110,1220)") ii.reset assert_equal(acollect(ii, l), "[c2](10,120;1010,1220)/[c3](0,100;1000,1200)") ii = RBA::RecursiveShapeIterator::new(l, c2, [0, 1], RBA::Box.new(-100, 0, 2000, 101), true) assert_equal(collect(ii, l), "[c2](0,100;1000,1200)/[c3](1100,100;2100,1200)") ii = RBA::RecursiveShapeIterator::new(l, c0, 0) assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)") ii.reset ii.unselect_cells("c0") ii.select_cells("c2") assert_equal(collect(ii, l), "[c2](100,0;1100,1100)/[c3](1200,0;2200,1100)") ii.reset_selection ii.unselect_cells("c*") ii.select_cells([ c2.cell_index ]) assert_equal(collect(ii, l), "[c2](100,0;1100,1100)") ii.reset_selection ii.unselect_all_cells ii.select_cells("c2") assert_equal(collect(ii, l), "[c2](100,0;1100,1100)") ii.reset_selection ii.select_all_cells ii.unselect_cells("c2") assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)") ii.reset_selection ii.select_cells("c*") ii.unselect_cells([ c1.cell_index, c2.cell_index ]) assert_equal(collect(ii, l), "[c0](0,100;1000,1200)/[c3](1200,0;2200,1100)/[c3](-1200,0;-100,1000)") end def test_2 # Recursive shape iterator tests l = RBA::Layout.new l.insert_layer_at(0, RBA::LayerInfo.new(1, 0)) l.insert_layer_at(1, RBA::LayerInfo.new(2, 0)) c0 = l.cell(l.add_cell("c0")) c1 = l.cell(l.add_cell("c1")) c2 = l.cell(l.add_cell("c2")) c3 = l.cell(l.add_cell("c3")) b = RBA::Box.new(0, 100, 1000, 1200) c3.shapes(0).insert(b) bb = RBA::Box.new(1, 101, 1001, 1201) c3.shapes(1).insert(bb) tt = RBA::Trans.new c0.insert(RBA::CellInstArray.new(c1.cell_index, tt)) c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100)))) c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1), RBA::Vector::new(10, 20), RBA::Vector::new(11, 21), 2, 3)) c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0)))) res = [] i = l.begin_shapes(c0.cell_index, 0) while !i.at_end? res << i.shape.box.transformed(i.trans).to_s + " " + i.path.collect { |e| "[" + l.cell(e.cell_inst.cell_index).name + " #" + e.ia.to_s + "," + e.ib.to_s + " -> " + e.specific_trans.to_s + "]" }.join("") i.next end assert_equal(res.join("\n") + "\n", <<"END") (1200,0;2200,1100) [c2 #-1,-1 -> r0 100,-100][c3 #-1,-1 -> r0 1100,0] (-1200,0;-100,1000) [c3 #0,0 -> r90 0,0] (-1190,20;-90,1020) [c3 #1,0 -> r90 10,20] (-1189,21;-89,1021) [c3 #0,1 -> r90 11,21] (-1179,41;-79,1041) [c3 #1,1 -> r90 21,41] (-1178,42;-78,1042) [c3 #0,2 -> r90 22,42] (-1168,62;-68,1062) [c3 #1,2 -> r90 32,62] END end end load("test_epilogue.rb")