Coverage for klayout_pex/rcx25/c/device_capacitor_plates.py: 100%
21 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#
24from __future__ import annotations
26from dataclasses import dataclass, field
27from typing import *
29import klayout.db as kdb
31from klayout_pex.klayout.lvsdb_extractor import DEVICE_CAPACITOR_PLATE_PROPERTY
32from klayout_pex.rcx25.types import NetName
34Shape = Union[kdb.PolygonWithProperties, kdb.EdgeWithProperties]
37@dataclass
38class DeviceCapacitorPlates:
39 """
40 The plates of the black-boxed capacitor devices, whose models have the capacitances between them
41 (the shapes of KIND_DEVICE_CAPACITOR_PLATE, e.g. the fingers of a MOM cap),
42 but not their capacitances to other nets (e.g. the substrate, a wire across), which are extracted.
44 NOTE: a pair of plates is of a device if its nets are the terminal nets of a device,
45 and not e.g. a wire of another net across the device, which is on its plate layers too
46 """
48 # the nets of the terminals of each device
49 terminal_net_pairs: Set[FrozenSet[NetName]] = field(default_factory=set)
51 @classmethod
52 def from_circuit(cls,
53 circuit: kdb.Circuit,
54 device_class_names: Set[str]) -> DeviceCapacitorPlates:
55 """
56 :param device_class_names: the device classes of the capacitors (e.g. the metal capacitors)
57 """
58 terminal_net_pairs: Set[FrozenSet[NetName]] = set()
59 for d in circuit.each_device():
60 if d.device_class().name not in device_class_names:
61 continue
62 net_names = sorted({net.expanded_name()
63 for td in d.device_class().terminal_definitions()
64 if (net := d.net_for_terminal(td.id())) is not None})
65 terminal_net_pairs.update(frozenset((n1, n2))
66 for idx, n1 in enumerate(net_names) for n2 in net_names[idx + 1:])
67 return DeviceCapacitorPlates(terminal_net_pairs=terminal_net_pairs)
69 def are_plates_of_a_device(self, shape1: Shape, net1: NetName, shape2: Shape, net2: NetName) -> bool:
70 """
71 :return: whether the shapes are plates of a device between their nets,
72 whose model has the capacitance between them
73 """
74 return bool(shape1.property(DEVICE_CAPACITOR_PLATE_PROPERTY)) and \
75 bool(shape2.property(DEVICE_CAPACITOR_PLATE_PROPERTY)) and \
76 frozenset((net1, net2)) in self.terminal_net_pairs