Coverage for klayout_pex/rcx25/extraction_results.py: 99%
91 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-17 17:24 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-17 17:24 +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#
24from __future__ import annotations
25from collections import defaultdict
26from dataclasses import dataclass, field
27from typing import *
29import klayout_pex_protobuf.process_parasitics_pb2 as process_parasitics_pb2
32NetName = str
33LayerName = str
34CellName = str
37@dataclass
38class NodeRegion:
39 layer_name: LayerName
40 net_name: NetName
41 cap_to_gnd: float
42 perimeter: float
43 area: float
46@dataclass(frozen=True)
47class SidewallKey:
48 layer: LayerName
49 net1: NetName
50 net2: NetName
53@dataclass
54class SidewallCap: # see Magic EdgeCap, extractInt.c L444
55 key: SidewallKey
56 cap_value: float # femto farad
57 distance: float # distance in µm
58 length: float # length in µm
59 tech_spec: process_parasitics_pb2.CapacitanceInfo.SidewallCapacitance
62@dataclass(frozen=True)
63class OverlapKey:
64 layer_top: LayerName
65 net_top: NetName
66 layer_bot: LayerName
67 net_bot: NetName
70@dataclass
71class OverlapCap:
72 key: OverlapKey
73 cap_value: float # femto farad
74 shielded_area: float # in µm^2
75 unshielded_area: float # in µm^2
76 tech_spec: process_parasitics_pb2.CapacitanceInfo.OverlapCapacitance
79@dataclass(frozen=True)
80class SideOverlapKey:
81 layer_inside: LayerName
82 net_inside: NetName
83 layer_outside: LayerName
84 net_outside: NetName
86 def __repr__(self) -> str:
87 return f"{self.layer_inside}({self.net_inside})-"\
88 f"{self.layer_outside}({self.net_outside})"
91@dataclass
92class SideOverlapCap:
93 key: SideOverlapKey
94 cap_value: float # femto farad
96 def __str__(self) -> str:
97 return f"(Side Overlap): {self.key} = {round(self.cap_value, 6)}fF"
100@dataclass(frozen=True)
101class NetCoupleKey:
102 net1: NetName
103 net2: NetName
105 def __repr__(self) -> str:
106 return f"{self.net1}-{self.net2}"
108 # NOTE: we norm net names alphabetically
109 def normed(self) -> NetCoupleKey:
110 if self.net1 < self.net2:
111 return self
112 else:
113 return NetCoupleKey(self.net2, self.net1)
116@dataclass
117class ExtractionSummary:
118 capacitances: Dict[NetCoupleKey, float]
120 @classmethod
121 def merged(cls, summaries: List[ExtractionSummary]) -> ExtractionSummary:
122 merged_capacitances = defaultdict(float)
123 for s in summaries:
124 for couple_key, cap in s.capacitances.items():
125 merged_capacitances[couple_key.normed()] += cap
126 return ExtractionSummary(merged_capacitances)
129@dataclass
130class CellExtractionResults:
131 cell_name: CellName
133 overlap_coupling: Dict[OverlapKey, OverlapCap] = field(default_factory=dict)
134 sidewall_table: Dict[SidewallKey, SidewallCap] = field(default_factory=dict)
135 sideoverlap_table: Dict[SideOverlapKey, SideOverlapCap] = field(default_factory=dict)
137 def summarize(self) -> ExtractionSummary:
138 overlap_summary = ExtractionSummary({
139 NetCoupleKey(key.net_top, key.net_bot): cap.cap_value
140 for key, cap in self.overlap_coupling.items()
141 })
143 sidewall_summary = ExtractionSummary({
144 NetCoupleKey(key.net1, key.net2): cap.cap_value
145 for key, cap in self.sidewall_table.items()
146 })
148 sideoverlap_summary = ExtractionSummary({
149 NetCoupleKey(key.net_inside, key.net_outside): cap.cap_value
150 for key, cap in self.sideoverlap_table.items()
151 })
153 return ExtractionSummary.merged([
154 overlap_summary, sidewall_summary, sideoverlap_summary
155 ])
158@dataclass
159class ExtractionResults:
160 cell_extraction_results: Dict[CellName, CellExtractionResults] = field(default_factory=dict)
162 def summarize(self) -> ExtractionSummary:
163 subsummaries = [s.summarize() for s in self.cell_extraction_results.values()]
164 return ExtractionSummary.merged(subsummaries)