pyedb 0.38.0__py3-none-any.whl → 0.39.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/common/nets.py +53 -139
- pyedb/configuration/cfg_components.py +1 -1
- pyedb/configuration/cfg_general.py +4 -2
- pyedb/configuration/cfg_modeler.py +1 -1
- pyedb/configuration/cfg_package_definition.py +1 -1
- pyedb/configuration/cfg_padstacks.py +1 -1
- pyedb/configuration/cfg_ports_sources.py +56 -23
- pyedb/configuration/configuration.py +18 -1
- pyedb/dotnet/{application → database}/Variables.py +21 -21
- pyedb/dotnet/{edb_core → database}/cell/connectable.py +5 -5
- pyedb/dotnet/{edb_core → database}/cell/hierarchy/component.py +11 -11
- pyedb/dotnet/{edb_core → database}/cell/hierarchy/hierarchy_obj.py +1 -1
- pyedb/dotnet/{edb_core → database}/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/{edb_core → database}/cell/layout.py +17 -17
- pyedb/dotnet/{edb_core → database}/cell/layout_obj.py +3 -3
- pyedb/dotnet/{edb_core → database}/cell/primitive/bondwire.py +1 -1
- pyedb/dotnet/{edb_core → database}/cell/primitive/path.py +4 -4
- pyedb/dotnet/{edb_core → database}/cell/primitive/primitive.py +14 -14
- pyedb/dotnet/{edb_core → database}/cell/terminal/bundle_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/edge_terminal.py +4 -4
- pyedb/dotnet/{edb_core → database}/cell/terminal/padstack_instance_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/pingroup_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/point_terminal.py +2 -2
- pyedb/dotnet/{edb_core → database}/cell/terminal/terminal.py +11 -11
- pyedb/dotnet/{edb_core → database}/cell/voltage_regulator.py +2 -2
- pyedb/dotnet/{edb_core → database}/components.py +101 -124
- pyedb/dotnet/{edb_core → database}/definition/component_def.py +5 -5
- pyedb/dotnet/{edb_core → database}/definition/component_model.py +1 -1
- pyedb/dotnet/{edb_core → database}/definition/definition_obj.py +1 -1
- pyedb/dotnet/{edb_core → database}/definition/definitions.py +2 -2
- pyedb/dotnet/{edb_core → database}/definition/package_def.py +4 -4
- pyedb/dotnet/{edb_core → database}/dotnet/database.py +8 -8
- pyedb/dotnet/{edb_core → database}/dotnet/primitive.py +9 -9
- pyedb/dotnet/{edb_core → database}/edb_data/control_file.py +12 -12
- pyedb/dotnet/{edb_core → database}/edb_data/hfss_extent_info.py +7 -7
- pyedb/dotnet/{edb_core → database}/edb_data/nets_data.py +10 -13
- pyedb/dotnet/{edb_core → database}/edb_data/padstacks_data.py +16 -16
- pyedb/dotnet/{edb_core → database}/edb_data/ports.py +4 -4
- pyedb/dotnet/{edb_core → database}/edb_data/primitives_data.py +5 -5
- pyedb/dotnet/{edb_core → database}/edb_data/raptor_x_simulation_setup_data.py +4 -4
- pyedb/dotnet/{edb_core → database}/edb_data/simulation_configuration.py +10 -10
- pyedb/dotnet/{edb_core → database}/edb_data/sources.py +4 -4
- pyedb/dotnet/{edb_core → database}/edb_data/variables.py +1 -1
- pyedb/dotnet/{edb_core → database}/geometry/polygon_data.py +4 -4
- pyedb/dotnet/{edb_core → database}/hfss.py +8 -8
- pyedb/dotnet/{edb_core → database}/layout_obj_instance.py +1 -1
- pyedb/dotnet/{edb_core → database}/layout_validation.py +2 -2
- pyedb/dotnet/{edb_core → database}/materials.py +23 -8
- pyedb/dotnet/{edb_core → database}/modeler.py +27 -27
- pyedb/dotnet/{edb_core → database}/net_class.py +8 -8
- pyedb/dotnet/{edb_core → database}/nets.py +12 -12
- pyedb/dotnet/{edb_core → database}/padstack.py +15 -15
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/mesh_operation.py +1 -1
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/settings.py +3 -3
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sim_setup_info.py +2 -2
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/simulation_settings.py +1 -1
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
- pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sweep_data.py +1 -1
- pyedb/dotnet/{edb_core → database}/siwave.py +10 -10
- pyedb/dotnet/{edb_core → database}/stackup.py +12 -12
- pyedb/dotnet/{edb_core → database}/utilities/hfss_simulation_setup.py +15 -15
- pyedb/dotnet/{edb_core → database}/utilities/obj_base.py +1 -1
- pyedb/dotnet/{edb_core → database}/utilities/simulation_setup.py +3 -3
- pyedb/dotnet/{edb_core → database}/utilities/siwave_simulation_setup.py +6 -6
- pyedb/dotnet/edb.py +117 -112
- pyedb/generic/design_types.py +26 -19
- pyedb/generic/general_methods.py +1 -1
- pyedb/generic/plot.py +0 -2
- pyedb/grpc/database/__init__.py +1 -0
- pyedb/grpc/database/components.py +2354 -0
- pyedb/grpc/database/control_file.py +1277 -0
- pyedb/grpc/database/definition/component_def.py +218 -0
- pyedb/grpc/database/definition/component_model.py +39 -0
- pyedb/grpc/database/definition/component_pin.py +32 -0
- pyedb/grpc/database/definition/materials.py +1207 -0
- pyedb/grpc/database/definition/n_port_component_model.py +34 -0
- pyedb/grpc/database/definition/package_def.py +227 -0
- pyedb/grpc/database/definition/padstack_def.py +842 -0
- pyedb/grpc/database/definitions.py +70 -0
- pyedb/grpc/database/general.py +43 -0
- pyedb/grpc/database/geometry/__init__.py +0 -0
- pyedb/grpc/database/geometry/arc_data.py +93 -0
- pyedb/grpc/database/geometry/point_3d_data.py +79 -0
- pyedb/grpc/database/geometry/point_data.py +30 -0
- pyedb/grpc/database/geometry/polygon_data.py +133 -0
- pyedb/grpc/database/hfss.py +1279 -0
- pyedb/grpc/database/hierarchy/__init__.py +0 -0
- pyedb/grpc/database/hierarchy/component.py +1301 -0
- pyedb/grpc/database/hierarchy/model.py +31 -0
- pyedb/grpc/database/hierarchy/netlist_model.py +30 -0
- pyedb/grpc/database/hierarchy/pin_pair_model.py +128 -0
- pyedb/grpc/database/hierarchy/pingroup.py +245 -0
- pyedb/grpc/database/hierarchy/s_parameter_model.py +33 -0
- pyedb/grpc/database/hierarchy/spice_model.py +48 -0
- pyedb/grpc/database/layers/__init__.py +0 -0
- pyedb/grpc/database/layers/layer.py +57 -0
- pyedb/grpc/database/layers/stackup_layer.py +410 -0
- pyedb/grpc/database/layout/__init__.py +0 -0
- pyedb/grpc/database/layout/cell.py +30 -0
- pyedb/grpc/database/layout/layout.py +196 -0
- pyedb/grpc/database/layout/voltage_regulator.py +149 -0
- pyedb/grpc/database/layout_validation.py +319 -0
- pyedb/grpc/database/modeler.py +1468 -0
- pyedb/grpc/database/net/__init__.py +0 -0
- pyedb/grpc/database/net/differential_pair.py +138 -0
- pyedb/grpc/database/net/extended_net.py +340 -0
- pyedb/grpc/database/net/net.py +198 -0
- pyedb/grpc/database/net/net_class.py +93 -0
- pyedb/grpc/database/nets.py +633 -0
- pyedb/grpc/database/padstacks.py +1500 -0
- pyedb/grpc/database/ports/__init__.py +0 -0
- pyedb/grpc/database/ports/ports.py +396 -0
- pyedb/grpc/database/primitive/__init__.py +3 -0
- pyedb/grpc/database/primitive/bondwire.py +181 -0
- pyedb/grpc/database/primitive/circle.py +75 -0
- pyedb/grpc/database/primitive/padstack_instance.py +1116 -0
- pyedb/grpc/database/primitive/path.py +346 -0
- pyedb/grpc/database/primitive/polygon.py +276 -0
- pyedb/grpc/database/primitive/primitive.py +739 -0
- pyedb/grpc/database/primitive/rectangle.py +146 -0
- pyedb/grpc/database/simulation_setup/__init__.py +0 -0
- pyedb/grpc/database/simulation_setup/adaptive_frequency.py +33 -0
- pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +32 -0
- pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +59 -0
- pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +35 -0
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +61 -0
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +78 -0
- pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +118 -0
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +355 -0
- pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +34 -0
- pyedb/grpc/database/simulation_setup/mesh_operation.py +34 -0
- pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +34 -0
- pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +33 -0
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +64 -0
- pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +125 -0
- pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +34 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +119 -0
- pyedb/grpc/database/simulation_setup/sweep_data.py +32 -0
- pyedb/grpc/database/siwave.py +1023 -0
- pyedb/grpc/database/source_excitations.py +2572 -0
- pyedb/grpc/database/stackup.py +2574 -0
- pyedb/grpc/database/terminal/__init__.py +0 -0
- pyedb/grpc/database/terminal/bundle_terminal.py +218 -0
- pyedb/grpc/database/terminal/edge_terminal.py +51 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +171 -0
- pyedb/grpc/database/terminal/pingroup_terminal.py +162 -0
- pyedb/grpc/database/terminal/point_terminal.py +99 -0
- pyedb/grpc/database/terminal/terminal.py +470 -0
- pyedb/grpc/database/utility/__init__.py +3 -0
- pyedb/grpc/database/utility/constants.py +25 -0
- pyedb/grpc/database/utility/heat_sink.py +124 -0
- pyedb/grpc/database/utility/hfss_extent_info.py +448 -0
- pyedb/grpc/database/utility/layout_statistics.py +277 -0
- pyedb/grpc/database/utility/rlc.py +80 -0
- pyedb/grpc/database/utility/simulation_configuration.py +3305 -0
- pyedb/grpc/database/utility/sources.py +388 -0
- pyedb/grpc/database/utility/sweep_data_distribution.py +83 -0
- pyedb/grpc/database/utility/xml_control_file.py +1277 -0
- pyedb/grpc/edb.py +4151 -0
- pyedb/grpc/edb_init.py +481 -0
- pyedb/grpc/rpc_session.py +177 -0
- pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +3 -2
- pyedb/ipc2581/ecad/cad_data/feature.py +4 -3
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +32 -20
- pyedb/ipc2581/ecad/cad_data/outline.py +3 -2
- pyedb/ipc2581/ecad/cad_data/package.py +4 -3
- pyedb/ipc2581/ecad/cad_data/path.py +82 -31
- pyedb/ipc2581/ecad/cad_data/polygon.py +122 -60
- pyedb/ipc2581/ecad/cad_data/profile.py +13 -12
- pyedb/ipc2581/ecad/cad_data/step.py +53 -21
- pyedb/ipc2581/ipc2581.py +47 -49
- pyedb/modeler/geometry_operators.py +1 -1
- {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/METADATA +5 -2
- pyedb-0.39.0.dist-info/RECORD +288 -0
- pyedb-0.38.0.dist-info/RECORD +0 -195
- /pyedb/dotnet/{edb_core → database}/__init__.py +0 -0
- /pyedb/dotnet/{application → database/cell}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/cell → database/cell/hierarchy}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/netlist_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/pin_pair_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/s_parameter_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/hierarchy/spice_model.py +0 -0
- /pyedb/dotnet/{edb_core → database}/cell/primitive/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/cell/hierarchy → database/cell/terminal}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/cell/terminal → database/definition}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/definition → database/dotnet}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core/dotnet → database/edb_data}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/design_options.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/edbvalue.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/layer_data.py +0 -0
- /pyedb/dotnet/{edb_core → database}/edb_data/utilities.py +0 -0
- /pyedb/dotnet/{edb_core → database}/general.py +0 -0
- /pyedb/dotnet/{edb_core/edb_data → database/geometry}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/geometry/point_data.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/adaptive_frequency_data.py +0 -0
- /pyedb/dotnet/{edb_core/geometry → database/sim_setup_data/io}/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/sim_setup_data/io/siwave.py +0 -0
- /pyedb/dotnet/{edb_core → database}/utilities/__init__.py +0 -0
- /pyedb/dotnet/{edb_core → database}/utilities/heatsink.py +0 -0
- /pyedb/{dotnet/edb_core/sim_setup_data/io → grpc/database/definition}/__init__.py +0 -0
- {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/LICENSE +0 -0
- {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from ansys.edb.core.layout.voltage_regulator import (
|
|
24
|
+
VoltageRegulator as GrpcVoltageRegulator,
|
|
25
|
+
)
|
|
26
|
+
from ansys.edb.core.utility.value import Value as GrpcValue
|
|
27
|
+
|
|
28
|
+
from pyedb.dotnet.database.edb_data.padstacks_data import EDBPadstackInstance
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class VoltageRegulator(GrpcVoltageRegulator):
|
|
32
|
+
"""Class managing voltage regulator."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, pedb, edb_object):
|
|
35
|
+
super().__init__(edb_object)
|
|
36
|
+
self._pedb = pedb
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def component(self):
|
|
40
|
+
"""Voltage regulator component
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
:class:`Component <pyedb.grpc.database.hierarchy.component.Component>`
|
|
45
|
+
Component.
|
|
46
|
+
"""
|
|
47
|
+
if not self.component.is_null:
|
|
48
|
+
ref_des = self.component.name
|
|
49
|
+
if not ref_des:
|
|
50
|
+
return False
|
|
51
|
+
return self._pedb.components.instances[ref_des]
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
@component.setter
|
|
55
|
+
def component(self, value):
|
|
56
|
+
if not isinstance(value, str):
|
|
57
|
+
self._pedb.logger.error("refdes name must be provided to set vrm component")
|
|
58
|
+
return
|
|
59
|
+
if value not in self._pedb.components.instances:
|
|
60
|
+
self._pedb.logger.error(f"component {value} not found in layout")
|
|
61
|
+
return
|
|
62
|
+
self.group = self._pedb.components.instances[value]
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def load_regulator_current(self):
|
|
66
|
+
"""Load regulator current value
|
|
67
|
+
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
float
|
|
71
|
+
Current value.
|
|
72
|
+
"""
|
|
73
|
+
return self.load_regulator_current.value
|
|
74
|
+
|
|
75
|
+
@load_regulator_current.setter
|
|
76
|
+
def load_regulator_current(self, value):
|
|
77
|
+
self.load_regulation_percent = GrpcValue(value)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def load_regulation_percent(self):
|
|
81
|
+
"""Retrieve load regulation percent value.
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
float
|
|
86
|
+
Percent value.
|
|
87
|
+
"""
|
|
88
|
+
return self.load_regulation_percent.value
|
|
89
|
+
|
|
90
|
+
@load_regulation_percent.setter
|
|
91
|
+
def load_regulation_percent(self, value):
|
|
92
|
+
self.load_regulation_percent = GrpcValue(value)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def negative_remote_sense_pin(self):
|
|
96
|
+
"""Retrieve negative remote sense pin.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
:class:`PadstackInstance pyedb.grpc.database.primitive.padstack_instance.PadstackInstance`
|
|
101
|
+
PadstackInstance.
|
|
102
|
+
"""
|
|
103
|
+
return self._pedb.padstacks.instances[self.negative_remote_sense_pin.id]
|
|
104
|
+
|
|
105
|
+
@negative_remote_sense_pin.setter
|
|
106
|
+
def negative_remote_sense_pin(self, value):
|
|
107
|
+
if isinstance(value, int):
|
|
108
|
+
if value in self._pedb.padsatcks.instances:
|
|
109
|
+
self.neg_remote_sense_pin = self._pedb.padsatcks.instances[value]
|
|
110
|
+
elif isinstance(value, EDBPadstackInstance):
|
|
111
|
+
self.neg_remote_sense_pin = value
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def positive_remote_sense_pin(self):
|
|
115
|
+
"""Retrieve positive remote sense pin.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
:class:`PadstackInstance pyedb.grpc.database.primitive.padstack_instance.PadstackInstance`
|
|
120
|
+
PadstackInstance.
|
|
121
|
+
"""
|
|
122
|
+
return self._pedb.padstacks.instances[self.pos_remote_sense_pin.id]
|
|
123
|
+
|
|
124
|
+
@positive_remote_sense_pin.setter
|
|
125
|
+
def positive_remote_sense_pin(self, value):
|
|
126
|
+
if isinstance(value, int):
|
|
127
|
+
if value in self._pedb.padsatcks.instances:
|
|
128
|
+
self.positive_remote_sense_pin = self._pedb.padsatcks.instances[value]
|
|
129
|
+
if not self.component:
|
|
130
|
+
self.component = self._pedb.padsatcks.instances[value].component.name
|
|
131
|
+
elif isinstance(value, EDBPadstackInstance):
|
|
132
|
+
self.positive_remote_sense_pin = value
|
|
133
|
+
if not self.component:
|
|
134
|
+
self.component = value.component.name
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def voltage(self):
|
|
138
|
+
"""Retrieve voltage value.
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
float
|
|
143
|
+
Voltage value.
|
|
144
|
+
"""
|
|
145
|
+
return self.voltage.value
|
|
146
|
+
|
|
147
|
+
@voltage.setter
|
|
148
|
+
def voltage(self, value):
|
|
149
|
+
self.voltage = GrpcValue(value)
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
import re
|
|
24
|
+
|
|
25
|
+
# from pyedb.generic.general_methods import generate_unique_name
|
|
26
|
+
# from pyedb.grpc.database.primitive.padstack_instances import PadstackInstance
|
|
27
|
+
# from pyedb.grpc.database.primitive.primitive import Primitive
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class LayoutValidation:
|
|
31
|
+
"""Manages all layout validation capabilities"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, pedb):
|
|
34
|
+
self._pedb = pedb
|
|
35
|
+
self._layout_instance = self._pedb.layout_instance
|
|
36
|
+
|
|
37
|
+
def dc_shorts(self, net_list=None, fix=False):
|
|
38
|
+
"""Find DC shorts on layout.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
net_list : str or list[str], optional
|
|
43
|
+
List of nets.
|
|
44
|
+
fix : bool, optional
|
|
45
|
+
If `True`, rename all the nets. (default)
|
|
46
|
+
If `False`, only report dc shorts.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
List[List[str, str]]
|
|
51
|
+
[[net name, net name]].
|
|
52
|
+
|
|
53
|
+
Examples
|
|
54
|
+
--------
|
|
55
|
+
|
|
56
|
+
>>> edb = Edb("edb_file")
|
|
57
|
+
>>> dc_shorts = edb.layout_validation.dc_shorts()
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
if not net_list:
|
|
61
|
+
net_list = list(self._pedb.nets.nets.keys())
|
|
62
|
+
elif isinstance(net_list, str):
|
|
63
|
+
net_list = [net_list]
|
|
64
|
+
_objects_list = {}
|
|
65
|
+
_padstacks_list = {}
|
|
66
|
+
for prim in self._pedb.modeler.primitives:
|
|
67
|
+
n_name = prim.net_name
|
|
68
|
+
if n_name in _objects_list:
|
|
69
|
+
_objects_list[n_name].append(prim)
|
|
70
|
+
else:
|
|
71
|
+
_objects_list[n_name] = [prim]
|
|
72
|
+
for pad in list(self._pedb.padstacks.instances.values()):
|
|
73
|
+
n_name = pad.net_name
|
|
74
|
+
if n_name in _padstacks_list:
|
|
75
|
+
_padstacks_list[n_name].append(pad)
|
|
76
|
+
else:
|
|
77
|
+
_padstacks_list[n_name] = [pad]
|
|
78
|
+
dc_shorts = []
|
|
79
|
+
all_shorted_nets = []
|
|
80
|
+
for net in net_list:
|
|
81
|
+
if net in all_shorted_nets:
|
|
82
|
+
continue
|
|
83
|
+
objs = []
|
|
84
|
+
for i in _objects_list.get(net, []):
|
|
85
|
+
objs.append(i)
|
|
86
|
+
for i in _padstacks_list.get(net, []):
|
|
87
|
+
objs.append(i)
|
|
88
|
+
if not len(objs):
|
|
89
|
+
self._pedb.nets[net].delete()
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
connected_objs = objs[0].get_connected_objects()
|
|
93
|
+
connected_objs.append(objs[0])
|
|
94
|
+
net_dc_shorts = [obj for obj in connected_objs]
|
|
95
|
+
all_shorted_nets.append(net)
|
|
96
|
+
if net_dc_shorts:
|
|
97
|
+
dc_nets = list(set([obj.net.name for obj in net_dc_shorts]))
|
|
98
|
+
dc_nets = [i for i in dc_nets if i != net]
|
|
99
|
+
for dc in dc_nets:
|
|
100
|
+
if dc:
|
|
101
|
+
dc_shorts.append([net, dc])
|
|
102
|
+
all_shorted_nets.append(dc)
|
|
103
|
+
if fix:
|
|
104
|
+
temp = []
|
|
105
|
+
for i in net_dc_shorts:
|
|
106
|
+
temp.append(i.net.name)
|
|
107
|
+
temp_key = set(temp)
|
|
108
|
+
temp_count = {temp.count(i): i for i in temp_key}
|
|
109
|
+
temp_count = dict(sorted(temp_count.items()))
|
|
110
|
+
while True:
|
|
111
|
+
temp_name = list(temp_count.values()).pop()
|
|
112
|
+
if not temp_name.lower().startswith("unnamed"):
|
|
113
|
+
break
|
|
114
|
+
elif temp_name.lower():
|
|
115
|
+
break
|
|
116
|
+
elif len(temp) == 0:
|
|
117
|
+
break
|
|
118
|
+
rename_shorts = [i for i in net_dc_shorts if i.net.name != temp_name]
|
|
119
|
+
for i in rename_shorts:
|
|
120
|
+
i.net = self._pedb.nets.nets[temp_name]
|
|
121
|
+
return dc_shorts
|
|
122
|
+
|
|
123
|
+
# def disjoint_nets(
|
|
124
|
+
# self,
|
|
125
|
+
# net_list=None,
|
|
126
|
+
# keep_only_main_net=False,
|
|
127
|
+
# clean_disjoints_less_than=0.0,
|
|
128
|
+
# order_by_area=False,
|
|
129
|
+
# keep_disjoint_pins=False,
|
|
130
|
+
# ):
|
|
131
|
+
# """Find and fix disjoint nets from a given netlist.
|
|
132
|
+
#
|
|
133
|
+
# Parameters
|
|
134
|
+
# ----------
|
|
135
|
+
# net_list : str, list, optional
|
|
136
|
+
# List of nets on which check disjoints. If `None` is provided then the algorithm will loop on all nets.
|
|
137
|
+
# keep_only_main_net : bool, optional
|
|
138
|
+
# Remove all secondary nets other than principal one (the one with more objects in it). Default is `False`.
|
|
139
|
+
# clean_disjoints_less_than : bool, optional
|
|
140
|
+
# Clean all disjoint nets with area less than specified area in square meters. Default is `0.0` to disable it.
|
|
141
|
+
# order_by_area : bool, optional
|
|
142
|
+
# Whether if the naming order has to be by number of objects (fastest) or area (slowest but more accurate).
|
|
143
|
+
# Default is ``False``.
|
|
144
|
+
# keep_disjoint_pins : bool, optional
|
|
145
|
+
# Whether if delete disjoints pins not connected to any other primitive or not. Default is ``False``.
|
|
146
|
+
#
|
|
147
|
+
# Returns
|
|
148
|
+
# -------
|
|
149
|
+
# List
|
|
150
|
+
# New nets created.
|
|
151
|
+
#
|
|
152
|
+
# Examples
|
|
153
|
+
# --------
|
|
154
|
+
#
|
|
155
|
+
# >>> renamed_nets = edb.layout_validation.disjoint_nets(["GND","Net2"])
|
|
156
|
+
# """
|
|
157
|
+
# from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
|
|
158
|
+
# timer_start = self._pedb.logger.reset_timer()
|
|
159
|
+
#
|
|
160
|
+
# if not net_list:
|
|
161
|
+
# net_list = list(self._pedb.nets.keys())
|
|
162
|
+
# elif isinstance(net_list, str):
|
|
163
|
+
# net_list = [net_list]
|
|
164
|
+
# _objects_list = {}
|
|
165
|
+
# _padstacks_list = {}
|
|
166
|
+
# for prim in self._pedb.modeler.primitives:
|
|
167
|
+
# if not prim.net.is_null:
|
|
168
|
+
# n_name = prim.net.name
|
|
169
|
+
# if n_name in _objects_list:
|
|
170
|
+
# _objects_list[n_name].append(prim)
|
|
171
|
+
# else:
|
|
172
|
+
# _objects_list[n_name] = [prim]
|
|
173
|
+
# for pad in list(self._pedb.padstacks.instances.values()):
|
|
174
|
+
# if not pad.net.is_null:
|
|
175
|
+
# n_name = pad.net_name
|
|
176
|
+
# if n_name in _padstacks_list:
|
|
177
|
+
# _padstacks_list[n_name].append(pad)
|
|
178
|
+
# else:
|
|
179
|
+
# _padstacks_list[n_name] = [pad]
|
|
180
|
+
# new_nets = []
|
|
181
|
+
# disjoints_objects = []
|
|
182
|
+
# self._pedb.logger.reset_timer()
|
|
183
|
+
# for net in net_list:
|
|
184
|
+
# net_groups = []
|
|
185
|
+
# obj_dict = {}
|
|
186
|
+
# for i in _objects_list.get(net, []):
|
|
187
|
+
# obj_dict[i.id] = i
|
|
188
|
+
# for i in _padstacks_list.get(net, []):
|
|
189
|
+
# obj_dict[i.id] = i
|
|
190
|
+
# objs = list(obj_dict.values())
|
|
191
|
+
# l = len(objs)
|
|
192
|
+
# while l > 0:
|
|
193
|
+
# l1 = self._layout_instance.get_connected_objects(objs[0].layout_object_instance, False)
|
|
194
|
+
# l1.append(objs[0].id)
|
|
195
|
+
# repetition = False
|
|
196
|
+
# for net_list in net_groups:
|
|
197
|
+
# if set(l1).intersection(net_list):
|
|
198
|
+
# net_groups.append([i for i in l1 if i not in net_list])
|
|
199
|
+
# repetition = True
|
|
200
|
+
# if not repetition:
|
|
201
|
+
# net_groups.append(l1)
|
|
202
|
+
# objs = [i for i in objs if i.id not in l1]
|
|
203
|
+
# l = len(objs)
|
|
204
|
+
# if len(net_groups) > 1:
|
|
205
|
+
#
|
|
206
|
+
# def area_calc(elem):
|
|
207
|
+
# sum = 0
|
|
208
|
+
# for el in elem:
|
|
209
|
+
# try:
|
|
210
|
+
# if el.layout_obj.obj_type.value == 0:
|
|
211
|
+
# if not el.is_void:
|
|
212
|
+
# sum += el.area()
|
|
213
|
+
# except:
|
|
214
|
+
# pass
|
|
215
|
+
# return sum
|
|
216
|
+
#
|
|
217
|
+
# if order_by_area:
|
|
218
|
+
# areas = [area_calc(i) for i in net_groups]
|
|
219
|
+
# sorted_list = [x for _, x in sorted(zip(areas, net_groups), reverse=True)]
|
|
220
|
+
# else:
|
|
221
|
+
# sorted_list = sorted(net_groups, key=len, reverse=True)
|
|
222
|
+
# for disjoints in sorted_list[1:]:
|
|
223
|
+
# if keep_only_main_net:
|
|
224
|
+
# for geo in disjoints:
|
|
225
|
+
# try:
|
|
226
|
+
# obj_dict[geo].delete()
|
|
227
|
+
# except KeyError:
|
|
228
|
+
# pass
|
|
229
|
+
# elif len(disjoints) == 1 and (
|
|
230
|
+
# clean_disjoints_less_than
|
|
231
|
+
# and "area" in dir(obj_dict[disjoints[0]])
|
|
232
|
+
# and obj_dict[disjoints[0]].area() < clean_disjoints_less_than
|
|
233
|
+
# ):
|
|
234
|
+
# try:
|
|
235
|
+
# obj_dict[disjoints[0]].delete()
|
|
236
|
+
# except KeyError:
|
|
237
|
+
# pass
|
|
238
|
+
# elif (
|
|
239
|
+
# len(disjoints) == 1
|
|
240
|
+
# and not keep_disjoint_pins
|
|
241
|
+
# and isinstance(obj_dict[disjoints[0]], PadstackInstance)
|
|
242
|
+
# ):
|
|
243
|
+
# try:
|
|
244
|
+
# obj_dict[disjoints[0]].delete()
|
|
245
|
+
# except KeyError:
|
|
246
|
+
# pass
|
|
247
|
+
#
|
|
248
|
+
# else:
|
|
249
|
+
# new_net_name = generate_unique_name(net, n=6)
|
|
250
|
+
# net_obj = self._pedb.nets.find_or_create_net(new_net_name)
|
|
251
|
+
# if net_obj:
|
|
252
|
+
# new_nets.append(net_obj.name)
|
|
253
|
+
# for geo in disjoints:
|
|
254
|
+
# try:
|
|
255
|
+
# obj_dict[geo].net_name = net_obj.name
|
|
256
|
+
# except KeyError:
|
|
257
|
+
# pass
|
|
258
|
+
# disjoints_objects.extend(disjoints)
|
|
259
|
+
# self._pedb._logger.info("Found {} objects in {} new nets.".format(len(disjoints_objects), len(new_nets)))
|
|
260
|
+
# self._pedb._logger.info_timer("Disjoint Cleanup Completed.", timer_start)
|
|
261
|
+
#
|
|
262
|
+
# return new_nets
|
|
263
|
+
|
|
264
|
+
def fix_self_intersections(self, net_list=None):
|
|
265
|
+
"""Find and fix self intersections from a given netlist.
|
|
266
|
+
|
|
267
|
+
Parameters
|
|
268
|
+
----------
|
|
269
|
+
net_list : str, list, optional
|
|
270
|
+
List of nets on which check disjoints. If `None` is provided then the algorithm will loop on all nets.
|
|
271
|
+
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
bool
|
|
275
|
+
"""
|
|
276
|
+
if not net_list:
|
|
277
|
+
net_list = list(self._pedb.nets.keys())
|
|
278
|
+
elif isinstance(net_list, str):
|
|
279
|
+
net_list = [net_list]
|
|
280
|
+
new_prims = []
|
|
281
|
+
for prim in self._pedb.modeler.polygons:
|
|
282
|
+
if prim.net_name in net_list:
|
|
283
|
+
new_prims.extend(prim.fix_self_intersections())
|
|
284
|
+
if new_prims:
|
|
285
|
+
self._pedb._logger.info("Self-intersections detected and removed.")
|
|
286
|
+
else:
|
|
287
|
+
self._pedb._logger.info("Self-intersection not found.")
|
|
288
|
+
return True
|
|
289
|
+
|
|
290
|
+
def illegal_net_names(self, fix=False):
|
|
291
|
+
"""Find and fix illegal net names."""
|
|
292
|
+
pattern = r"[\(\)\\\/:;*?<>\'\"|`~$]"
|
|
293
|
+
|
|
294
|
+
nets = self._pedb.nets.nets
|
|
295
|
+
|
|
296
|
+
renamed_nets = []
|
|
297
|
+
for net, val in nets.items():
|
|
298
|
+
if re.findall(pattern, net):
|
|
299
|
+
renamed_nets.append(net)
|
|
300
|
+
if fix:
|
|
301
|
+
new_name = re.sub(pattern, "_", net)
|
|
302
|
+
val.name = new_name
|
|
303
|
+
|
|
304
|
+
self._pedb._logger.info("Found {} illegal net names.".format(len(renamed_nets)))
|
|
305
|
+
return
|
|
306
|
+
|
|
307
|
+
def illegal_rlc_values(self, fix=False):
|
|
308
|
+
"""Find and fix RLC illegal values."""
|
|
309
|
+
inductors = self._pedb.components.inductors
|
|
310
|
+
|
|
311
|
+
temp = []
|
|
312
|
+
for k, v in inductors.items():
|
|
313
|
+
model = v.component_property.model
|
|
314
|
+
if not len(model.pin_pairs): # pragma: no cover
|
|
315
|
+
temp.append(k)
|
|
316
|
+
if fix:
|
|
317
|
+
v.rlc_values = [0, 1, 0]
|
|
318
|
+
self._pedb._logger.info(f"Found {len(temp)} inductors have no value.")
|
|
319
|
+
return
|