Coverage for tests/rcx25/resistor_extraction_test.py: 100%
95 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-03-31 19:36 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-03-31 19:36 +0000
1#
2# --------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: 2024 Martin Jan Köhler and Harald Pretl
4# Johannes Kepler University, Institute for Integrated Circuits.
5#
6# This file is part of KPEX
7# (see https://github.com/martinjankoehler/klayout-pex).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
21# SPDX-License-Identifier: GPL-3.0-or-later
22# --------------------------------------------------------------------------------
23#
25import allure
26import unittest
27import klayout_pex.rcx25.r.resistor_extraction as rex
28import klayout.db as kdb
31@allure.parent_suite("Unit Tests")
32class REXTest(unittest.TestCase):
33 def test_conductance(self):
34 c1 = rex.Conductance(1.0)
35 c2 = rex.Conductance(0.25)
36 self.assertEqual(str(c1.parallel(c2)), "1.25")
37 self.assertEqual(str(c1.serial(c2)), "0.2")
39 def test_rex_basic(self):
40 ex = rex.ResistorNetwork()
41 self.assertEqual(ex.check(), 0)
42 self.assertEqual("\n" + str(ex) + "\n", """
43Nodes:
44Conductors:
45""")
47 nid = ex.node_id(kdb.Point(100, 200))
48 nid2 = ex.node_id(kdb.Point(100, 200))
49 self.assertEqual(nid, nid2)
50 self.assertEqual(str(ex.location(nid)), "100,200")
51 self.assertEqual(ex.check(), 0)
52 self.assertEqual("\n" + str(ex) + "\n", """
53Nodes:
54 0: 100,200
55Conductors:
56""")
58 nid2 = ex.node_id(kdb.Point(200, 100))
59 self.assertNotEqual(nid, nid2)
60 self.assertEqual(ex.check(), 0)
61 self.assertEqual("\n" + str(ex) + "\n", """
62Nodes:
63 0: 100,200
64 1: 200,100
65Conductors:
66""")
67 ex.add_cond(nid, nid2, rex.Conductance(0.25))
68 self.assertEqual(ex.check(), 0)
69 self.assertEqual("\n" + str(ex) + "\n", """
70Nodes:
71 0: 100,200
72 1: 200,100
73Conductors:
74 0,1: 0.25
75""")
76 ex.add_cond(nid, nid2, rex.Conductance(0.75))
77 self.assertEqual(ex.check(), 0)
78 self.assertEqual("\n" + str(ex) + "\n", """
79Nodes:
80 0: 100,200
81 1: 200,100
82Conductors:
83 0,1: 1
84""")
86 nid3 = ex.node_id(kdb.Point(0, 0))
87 ex.add_cond(nid, nid3, rex.Conductance(0.5))
88 ex.add_cond(nid2, nid3, rex.Conductance(1.0))
89 self.assertEqual(ex.check(), 0)
90 self.assertEqual("\n" + str(ex) + "\n", """
91Nodes:
92 0: 100,200
93 1: 200,100
94 2: 0,0
95Conductors:
96 0,1: 1
97 0,2: 0.5
98 1,2: 1
99""")
101 ex.connect_nodes(nid, nid3)
102 self.assertEqual(ex.check(), 0)
103 self.assertEqual("\n" + str(ex) + "\n", """
104Nodes:
105 0: 100,200
106 1: 200,100
107Conductors:
108 0,1: 2
109""")
111 def test_rn_eliminate(self):
112 ex = rex.ResistorNetwork()
114 nid1 = ex.node_id(kdb.Point(100, 200))
115 nid2 = ex.node_id(kdb.Point(200, 100))
116 nid3 = ex.node_id(kdb.Point(0, -200))
117 nid4 = ex.node_id(kdb.Point(0, 0))
118 ex.add_cond(nid1, nid2, rex.Conductance(1.0))
119 ex.add_cond(nid1, nid3, rex.Conductance(0.5))
120 ex.add_cond(nid2, nid3, rex.Conductance(2.0))
121 ex.add_cond(nid1, nid4, rex.Conductance(1.0))
122 ex.add_cond(nid2, nid4, rex.Conductance(2.0))
123 ex.add_cond(nid3, nid4, rex.Conductance(0.5))
124 self.assertEqual(ex.check(), 0)
125 self.assertEqual("\n" + str(ex) + "\n", """
126Nodes:
127 0: 100,200
128 1: 200,100
129 2: 0,-200
130 3: 0,0
131Conductors:
132 0,1: 1
133 0,2: 0.5
134 0,3: 1
135 1,2: 2
136 1,3: 2
137 2,3: 0.5
138""")
140 ex.eliminate_node(nid4)
141 self.assertEqual(ex.check(), 0)
142 self.assertEqual("\n" + str(ex) + "\n", """
143Nodes:
144 0: 100,200
145 1: 200,100
146 2: 0,-200
147Conductors:
148 0,1: 1.57143
149 0,2: 0.642857
150 1,2: 2.28571
151""")
153 def test_rn_eliminate2(self):
154 ex = rex.ResistorNetwork()
156 nid1 = ex.node_id(kdb.Point(100, 200))
157 nid2 = ex.node_id(kdb.Point(200, 100))
158 nid3 = ex.node_id(kdb.Point(0, -200))
159 nid4 = ex.node_id(kdb.Point(0, 0))
161 ex.add_cond(nid1, nid2, rex.Conductance(1.0))
162 ex.add_cond(nid1, nid3, rex.Conductance(0.5))
163 ex.add_cond(nid2, nid3, rex.Conductance(2.0))
164 ex.add_cond(nid1, nid4, rex.Conductance(1.0))
165 ex.add_cond(nid2, nid4, rex.Conductance(2.0))
166 ex.add_cond(nid3, nid4, rex.Conductance(0.5))
167 self.assertEqual(ex.check(), 0)
169 ex.mark_precious(nid1)
170 ex.mark_precious(nid4)
172 ex.eliminate_all()
173 self.assertEqual(ex.check(), 0)
175 self.assertEqual("\n" + str(ex) + "\n", """
176Nodes:
177 0: 100,200
178 3: 0,0
179Conductors:
180 0,3: 1.93182
181""")
183 def test_expand_skinny_tris(self):
184 # non-skinny
185 p = kdb.Polygon([(0, 0), (2000, -10000), (5000, 0)])
186 pp = rex.ResistorNetwork.expand_skinny_tris(p)
187 self.assertEqual("\n" + "\n".join([str(p) for p in pp]) + "\n", """
188(2000,-10000;0,0;5000,0)
189""")
191 # non-skinny (exactly 90 degree)
192 p = kdb.Polygon([(0, 0), (2000, -2000), (4000, 0)])
193 pp = rex.ResistorNetwork.expand_skinny_tris(p)
194 self.assertEqual("\n" + "\n".join([str(p) for p in pp]) + "\n", """
195(2000,-2000;0,0;4000,0)
196""")
198 # skinny (angle >90 degree)
199 p = kdb.Polygon([(0, 0), (2000, -1000), (5000, 0)])
200 pp = rex.ResistorNetwork.expand_skinny_tris(p)
201 self.assertEqual("\n" + "\n".join([str(p) for p in pp]) + "\n", """
202(2000,-1000;2000,0;5000,0)
203(2000,-1000;0,0;2000,0)
204""")
206 def test_extraction(self):
207 rx = rex.ResistorExtraction(b=1.0)
209 polygons = kdb.Region(kdb.Box(0, 0, 10000, 1000))
211 pins = kdb.Region()
212 pins.insert(kdb.Box(0, 0, 1000, 1000))
213 pins.insert(kdb.Box(9000, 0, 10000, 1000))
215 labels = kdb.Texts()
216 labels.insert(kdb.Text("A", kdb.Trans(500, 500)))
217 labels.insert(kdb.Text("B", kdb.Trans(9500, 500)))
219 rn = rx.extract(polygons, pins, labels)
220 self.assertEqual("\n" + "\n".join([n.to_string(True) for n in rn]) + "\n", """
221Nodes:
222 A: 1000,1000
223 B: 9000,0
224Resistors:
225 A,B: 8
226""")