Coverage for tests/rcx25/device_capacitor_plates_test.py: 100%
34 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-02 23:32 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-02 23:32 +0000
1#
2# --------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: 2024-2026 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/iic-jku/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
28import klayout.db as kdb
30from klayout_pex.klayout.lvsdb_extractor import DEVICE_CAPACITOR_PLATE_PROPERTY
31from klayout_pex.rcx25.c.device_capacitor_plates import DeviceCapacitorPlates
34def netlist() -> kdb.Netlist:
35 """
36 A MOM cap between the nets A and B, and an nmos between A and C
37 """
38 netlist = kdb.Netlist()
39 circuit = kdb.Circuit()
40 circuit.name = 'chip'
41 netlist.add(circuit)
42 nets = {name: circuit.create_net(name) for name in ('A', 'B', 'C')}
43 for device_class, class_name, device_name, terminal_nets in (
44 (kdb.DeviceClassCapacitor(), 'mom', 'C1', {'A': 'A', 'B': 'B'}),
45 (kdb.DeviceClassMOS4Transistor(), 'nmos', 'M1', {'D': 'A', 'S': 'C'})):
46 device_class.name = class_name
47 netlist.add(device_class)
48 device = circuit.create_device(device_class, device_name)
49 for terminal, net_name in terminal_nets.items():
50 device.connect_terminal(terminal, nets[net_name])
51 return netlist
54def shape(net: str, plate: bool) -> kdb.PolygonWithProperties:
55 properties = {'net': net, DEVICE_CAPACITOR_PLATE_PROPERTY: True} if plate else {'net': net}
56 return kdb.PolygonWithProperties(kdb.Polygon(kdb.Box(0, 0, 100, 100)), properties)
59@allure.parent_suite("Unit Tests")
60@allure.tag("RCX25", "Capacitance", "Device Capacitor Plates")
61class Test(unittest.TestCase):
62 def test_terminal_nets_of_the_capacitor_devices(self):
63 chip = netlist()
64 plates = DeviceCapacitorPlates.from_circuit(chip.circuit_by_name('chip'), device_class_names={'mom'})
65 self.assertEqual({frozenset(('A', 'B'))}, plates.terminal_net_pairs)
67 def test_plates_of_a_device(self):
68 chip = netlist()
69 plates = DeviceCapacitorPlates.from_circuit(chip.circuit_by_name('chip'), device_class_names={'mom'})
70 self.assertTrue(plates.are_plates_of_a_device(shape('A', plate=True), 'A', shape('B', plate=True), 'B'))
71 # e.g. a wire of the net B, outside of the device
72 self.assertFalse(plates.are_plates_of_a_device(shape('A', plate=True), 'A', shape('B', plate=False), 'B'))
73 # e.g. a wire of the net C across the device, on its plate layers too
74 self.assertFalse(plates.are_plates_of_a_device(shape('A', plate=True), 'A', shape('C', plate=True), 'C'))