# encoding: UTF-8 # KLayout Layout Viewer # Copyright (C) 2006-2025 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 PEX_TestClass < TestBase # PEX basics def test_1_Basic rn = RBA::RNetwork::new a = rn.create_node(RBA::RNode::VertexPort, 1) b = rn.create_node(RBA::RNode::Internal, 2) c = rn.create_node(RBA::RNode::PolygonPort, 3) d = rn.create_node(RBA::RNode::PolygonPort, 3, 17) assert_equal(a.type, RBA::RNode::VertexPort) assert_equal(a.port_index, 1) assert_equal(a.object_id, a.object_id) assert_not_equal(a.object_id, b.object_id) assert_equal(a.to_s, "V1") assert_equal(b.to_s, "$2") assert_equal(c.to_s, "P3") assert_equal(d.to_s, "P3.17") rab = rn.create_element(1.0, a, b) assert_equal(rab.a.object_id, a.object_id) assert_equal(rab.b.object_id, b.object_id) assert_equal(rab.to_s, "R $2 V1 1") rn.create_element(1.0, a, b) assert_equal(rab.to_s, "R $2 V1 0.5") rbc = rn.create_element(1.0, b, c) assert_equal(rn.to_s, "R $2 V1 0.5\n" + "R $2 P3 1") assert_equal(b.each_element.collect(&:to_s).sort.join(";"), "R $2 P3 1;R $2 V1 0.5") assert_equal(rn.each_element.collect(&:to_s).sort.join(";"), "R $2 P3 1;R $2 V1 0.5") assert_equal(rn.each_node.collect(&:to_s).sort.join(";"), "$2;P3;P3.17;V1") rn.simplify assert_equal(rn.to_s, "R P3 V1 1.5") rn.clear assert_equal(rn.to_s, "") end def test_2_Destroy rn = RBA::RNetwork::new a = rn.create_node(RBA::RNode::VertexPort, 1) b = rn.create_node(RBA::RNode::Internal, 2) rab = rn.create_element(1.0, a, b) # this should invalid the pointers rn._destroy begin assert_equal(a.to_s, "") rescue => ex # graph has been destroyed already end begin assert_equal(rab.to_s, "") rescue => ex # graph has been destroyed already end end def test_3_SQC poly = RBA::Polygon::new(RBA::Box::new(0, 0, 1100, 100)) vp = [ RBA::Point::new(50, 50) ] pp = [ RBA::Polygon::new(RBA::Box::new(1000, 0, 1100, 100)) ] rex = RBA::RExtractor::square_counting_extractor(0.001) rn = rex.extract(poly, vp, pp) assert_equal(rn.to_s, "R P0 V0 10") end def test_3_TX poly = RBA::Polygon::new(RBA::Box::new(0, 0, 1100, 100)) vp = [ RBA::Point::new(50, 50) ] pp = [ RBA::Polygon::new(RBA::Box::new(1000, 0, 1100, 100)) ] rex = RBA::RExtractor::tesselation_extractor(0.001, 0.8) rn = rex.extract(poly, vp, pp) assert_equal(rn.to_s, "R P0 V0 9.44") end def test_4_ExtractorTech l1 = 1 l2 = 2 l3 = 3 tech = RBA::RExtractorTech::new tech.skip_simplify = true assert_equal(tech.skip_simplify, true) tech.skip_simplify = false assert_equal(tech.skip_simplify, false) via1 = RBA::RExtractorTechVia::new via1.bottom_conductor = l1 via1.cut_layer = l2 via1.top_conductor = l3 via1.resistance = 2.0 via1.merge_distance = 0.2 assert_equal(via1.to_s, "Via(bottom=L1, cut=L2, top=L3, R=2 µm²*Ohm, d_merge=0.2 µm)") assert_equal(via1.bottom_conductor, l1) assert_equal(via1.cut_layer, l2) assert_equal(via1.top_conductor, l3) assert_equal(via1.resistance, 2.0) assert_equal(via1.merge_distance.to_s, "0.2") tech.add_via(via1) assert_equal(tech.each_via.collect { |v| v.cut_layer }, [ l2 ]) tech.clear_vias assert_equal(tech.each_via.collect { |v| v.cut_layer }, []) tech.add_via(via1) assert_equal(tech.each_via.collect { |v| v.cut_layer }, [ l2 ]) cond1 = RBA::RExtractorTechConductor::new cond1.layer = l1 cond1.resistance = 0.5 assert_equal(cond1.to_s, "Conductor(layer=L1, R=0.5 Ohm/sq, algo=SquareCounting)") assert_equal(cond1.layer, l1) assert_equal(cond1.resistance, 0.5) cond2 = RBA::RExtractorTechConductor::new cond2.layer = l3 cond2.resistance = 0.25 tech.add_conductor(cond2) assert_equal(tech.each_conductor.collect { |c| c.layer }, [ l3 ]) assert_equal(tech.to_s, "Via(bottom=L1, cut=L2, top=L3, R=2 µm²*Ohm, d_merge=0.2 µm)\n" + "Conductor(layer=L3, R=0.25 Ohm/sq, algo=SquareCounting)" ) tech.clear_conductors assert_equal(tech.each_conductor.collect { |c| c.layer }, []) tech.add_conductor(cond1) tech.add_conductor(cond2) assert_equal(tech.each_conductor.collect { |c| c.layer }, [ l1, l3 ]) end # A complete, small example for a R network extraction def test_5_NetEx ly = RBA::Layout::new ly.read(File.join($ut_testsrc, "testdata", "pex", "netex_test1.gds")) rex = RBA::RNetExtractor::new(ly.dbu) tc = ly.top_cell l1 = ly.layer(1, 0) l1p = ly.layer(1, 1) l1v = ly.layer(1, 2) l2 = ly.layer(2, 0) l3 = ly.layer(3, 0) l3p = ly.layer(3, 1) l3v = ly.layer(3, 2) # That is coincidence, but it needs to be that way for the strings to match assert_equal(l1, 1) assert_equal(l2, 0) assert_equal(l3, 2) geo = {} [ l1, l2, l3 ].each do |l| geo[l] = RBA::Region::new(tc.begin_shapes_rec(l)) end tech = RBA::RExtractorTech::new via1 = RBA::RExtractorTechVia::new via1.bottom_conductor = l1 via1.cut_layer = l2 via1.top_conductor = l3 via1.resistance = 2.0 via1.merge_distance = 0.2 tech.add_via(via1) cond1 = RBA::RExtractorTechConductor::new cond1.layer = l1 cond1.resistance = 0.5 cond2 = RBA::RExtractorTechConductor::new cond2.layer = l3 cond2.resistance = 0.25 tech.add_conductor(cond1) tech.add_conductor(cond2) polygon_ports = { } polygon_ports[l1] = RBA::Region::new(tc.begin_shapes_rec(l1p)).each_merged.to_a polygon_ports[l3] = RBA::Region::new(tc.begin_shapes_rec(l3p)).each_merged.to_a vertex_ports = { } vertex_ports[l1] = RBA::Region::new(tc.begin_shapes_rec(l1v)).each_merged.collect { |p| p.bbox.center } vertex_ports[l3] = RBA::Region::new(tc.begin_shapes_rec(l3v)).each_merged.collect { |p| p.bbox.center } network = rex.extract(tech, geo, vertex_ports, polygon_ports) n = network.to_s(true) n = n.gsub(/ \$\d+\./, " $x.") n = n.split("\n").sort.join("\n") + "\n" assert_equal(n, <<"END") R $x.1(9.3,-5.9;9.9,-5.3) $x.2(10,-3.5;10,-2.7) 13.2813 R $x.1(9.3,-5.9;9.9,-5.3) P0.1(12.9,-5.9;13.5,-5.3) 2.25 R $x.1(9.3,-5.9;9.9,-5.3) V0.2(0.3,-5.7;0.5,-5.5) 55.75 R $x.2(10,-3.5;10,-2.7) P0.2(12.9,-3.4;13.5,-2.8) 1 R $x.2(10,-3.5;10,-2.7) V0.1(5.2,0.4;5.2,0.4) 28.7812 R V0.1(5.2,0.4;5.2,0.4) V0.2(0.3,-5.7;0.5,-5.5) 17.375 END end end load("test_epilogue.rb")