Coverage for tests/rcx25/rcx25_netlist_expander_whitebox_test.py: 100%
48 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.device_models import DeviceModels
31from klayout_pex.rcx25.extraction_results import CellExtractionResults, ExtractionResults
32from klayout_pex.rcx25.netlist_expander import RCX25NetlistExpander
33import klayout_pex_protobuf.kpex.tech.device_models_pb2 as device_models_pb2
36def device_models(*metal_capacitor_class_names: str) -> DeviceModels:
37 info = device_models_pb2.DeviceModelsInfo()
38 for name in metal_capacitor_class_names:
39 info.device_model_mappings.add(lvs_device_class_name=name,
40 kind=device_models_pb2.DeviceModelMapping.KIND_METAL_CAPACITOR)
41 return DeviceModels(info)
44def whiteboxed_device_names(netlist: kdb.Netlist, device_models: DeviceModels) -> list:
45 expanded = RCX25NetlistExpander.expand(netlist, 'chip',
46 ExtractionResults({'chip': CellExtractionResults(cell_name='chip')}),
47 blackbox_devices=False,
48 device_models=device_models)
49 device_class_names = {dc.name for dc in netlist.each_device_class()}
50 return [d.name for d in expanded.circuit_by_name('chip').each_device()
51 if d.device_class().name in device_class_names]
54@allure.parent_suite("Unit Tests")
55@allure.tag("RCX25", "Netlist Expansion")
56class Test(unittest.TestCase):
57 def test_whitebox_removes_all_capacitors(self):
58 # Removing a device ended the iteration over the devices,
59 # so only the first capacitor was removed, and the others were counted twice:
60 # as device and as extracted geometry
61 netlist = kdb.Netlist()
62 circuit = kdb.Circuit()
63 circuit.name = 'chip'
64 netlist.add(circuit)
65 mim = kdb.DeviceClassCapacitor()
66 mim.name = 'mim'
67 netlist.add(mim)
68 nmos = kdb.DeviceClassMOS4Transistor()
69 nmos.name = 'nmos'
70 netlist.add(nmos)
71 for name in ('C1', 'C2', 'C3'):
72 circuit.create_device(mim, name)
73 circuit.create_device(nmos, 'M1')
75 self.assertEqual(['M1'], whiteboxed_device_names(netlist, device_models('mim')))
77 def test_whitebox_removes_the_metal_capacitors_whatever_their_device_class(self):
78 # The devices were removed by their device class: sky130A reads VPP caps with 4 terminals as MOS4,
79 # so they were kept, and counted twice (as device and as extracted geometry),
80 # while the MOS capacitors are capacitor classes, so they were removed,
81 # and their capacitance was lost, which the extraction doesn't have
82 netlist = kdb.Netlist()
83 circuit = kdb.Circuit()
84 circuit.name = 'chip'
85 netlist.add(circuit)
86 vpp = kdb.DeviceClassMOS4Transistor()
87 vpp.name = 'vpp'
88 netlist.add(vpp)
89 mos_cap = kdb.DeviceClassCapacitor()
90 mos_cap.name = 'mos_cap'
91 netlist.add(mos_cap)
92 circuit.create_device(vpp, 'X1')
93 circuit.create_device(mos_cap, 'C1')
95 self.assertEqual(['C1'], whiteboxed_device_names(netlist, device_models('vpp')))