pyedb 0.56.0__py3-none-any.whl → 0.58.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/configuration/cfg_data.py +3 -0
- pyedb/configuration/cfg_pin_groups.py +2 -0
- pyedb/configuration/cfg_terminals.py +232 -0
- pyedb/configuration/configuration.py +146 -3
- pyedb/dotnet/clr_module.py +1 -2
- pyedb/dotnet/database/Variables.py +30 -22
- pyedb/dotnet/database/cell/hierarchy/component.py +2 -8
- pyedb/dotnet/database/cell/layout.py +5 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
- pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
- pyedb/dotnet/database/components.py +15 -19
- pyedb/dotnet/database/dotnet/database.py +1 -0
- pyedb/dotnet/database/edb_data/control_file.py +19 -8
- pyedb/dotnet/database/edb_data/nets_data.py +3 -3
- pyedb/dotnet/database/edb_data/padstacks_data.py +39 -14
- pyedb/dotnet/database/edb_data/ports.py +0 -25
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
- pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +21 -2
- pyedb/dotnet/database/general.py +1 -6
- pyedb/dotnet/database/hfss.py +9 -8
- pyedb/dotnet/database/layout_validation.py +14 -3
- pyedb/dotnet/database/materials.py +1 -3
- pyedb/dotnet/database/modeler.py +7 -3
- pyedb/dotnet/database/nets.py +27 -19
- pyedb/dotnet/database/padstack.py +4 -2
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +54 -1
- pyedb/dotnet/database/siwave.py +4 -3
- pyedb/dotnet/database/stackup.py +55 -58
- pyedb/dotnet/database/utilities/heatsink.py +0 -1
- pyedb/dotnet/database/utilities/hfss_simulation_setup.py +81 -0
- pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +264 -13
- pyedb/dotnet/edb.py +65 -47
- pyedb/exceptions.py +1 -2
- pyedb/extensions/create_cell_array.py +67 -49
- pyedb/generic/data_handlers.py +13 -23
- pyedb/generic/design_types.py +9 -35
- pyedb/generic/filesystem.py +4 -2
- pyedb/generic/general_methods.py +28 -41
- pyedb/generic/plot.py +8 -23
- pyedb/generic/process.py +78 -10
- pyedb/grpc/database/_typing.py +0 -0
- pyedb/grpc/database/components.py +14 -13
- pyedb/grpc/database/control_file.py +27 -40
- pyedb/grpc/database/definition/materials.py +1 -1
- pyedb/grpc/database/definition/package_def.py +6 -3
- pyedb/grpc/database/definition/padstack_def.py +14 -12
- pyedb/grpc/database/hfss.py +1 -4
- pyedb/grpc/database/hierarchy/component.py +5 -13
- pyedb/grpc/database/hierarchy/pingroup.py +16 -3
- pyedb/grpc/database/layers/layer.py +1 -2
- pyedb/grpc/database/layers/stackup_layer.py +42 -19
- pyedb/grpc/database/layout/layout.py +43 -27
- pyedb/grpc/database/layout/voltage_regulator.py +6 -1
- pyedb/grpc/database/layout_validation.py +5 -2
- pyedb/grpc/database/modeler.py +254 -252
- pyedb/grpc/database/net/differential_pair.py +9 -2
- pyedb/grpc/database/net/extended_net.py +24 -9
- pyedb/grpc/database/net/net.py +14 -5
- pyedb/grpc/database/net/net_class.py +24 -7
- pyedb/grpc/database/nets.py +11 -43
- pyedb/grpc/database/padstacks.py +67 -119
- pyedb/grpc/database/primitive/bondwire.py +3 -67
- pyedb/grpc/database/primitive/circle.py +42 -3
- pyedb/grpc/database/primitive/padstack_instance.py +58 -31
- pyedb/grpc/database/primitive/path.py +160 -11
- pyedb/grpc/database/primitive/polygon.py +73 -7
- pyedb/grpc/database/primitive/primitive.py +2 -2
- pyedb/grpc/database/primitive/rectangle.py +105 -4
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +79 -0
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +1 -0
- pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
- pyedb/grpc/database/siwave.py +6 -13
- pyedb/grpc/database/source_excitations.py +46 -63
- pyedb/grpc/database/stackup.py +55 -60
- pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +9 -11
- pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
- pyedb/grpc/database/terminal/point_terminal.py +30 -0
- pyedb/grpc/database/terminal/terminal.py +35 -10
- pyedb/grpc/database/utility/heat_sink.py +0 -1
- pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
- pyedb/grpc/database/utility/xml_control_file.py +19 -8
- pyedb/grpc/edb.py +63 -32
- pyedb/grpc/edb_init.py +1 -0
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
- pyedb/ipc2581/ecad/cad_data/step.py +1 -1
- pyedb/ipc2581/ipc2581.py +8 -7
- pyedb/libraries/common.py +3 -4
- pyedb/libraries/rf_libraries/base_functions.py +7 -16
- pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
- pyedb/misc/aedtlib_personalib_install.py +2 -2
- pyedb/misc/downloads.py +19 -3
- pyedb/misc/misc.py +5 -2
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +3 -2
- pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +0 -1
- pyedb/misc/utilities.py +0 -1
- pyedb/modeler/geometry_operators.py +3 -2
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/METADATA +6 -7
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/RECORD +110 -108
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/WHEEL +0 -0
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -20,15 +20,18 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
+
from __future__ import annotations
|
|
23
24
|
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from pyedb.grpc.database.net.net import Net
|
|
24
29
|
import re
|
|
25
30
|
|
|
26
31
|
from ansys.edb.core.net.differential_pair import (
|
|
27
32
|
DifferentialPair as GrpcDifferentialPair,
|
|
28
33
|
)
|
|
29
34
|
|
|
30
|
-
from pyedb.grpc.database.net.net import Net
|
|
31
|
-
|
|
32
35
|
|
|
33
36
|
class DifferentialPairs:
|
|
34
37
|
def __init__(self, pedb):
|
|
@@ -131,9 +134,13 @@ class DifferentialPair(GrpcDifferentialPair):
|
|
|
131
134
|
@property
|
|
132
135
|
def positive_net(self) -> Net:
|
|
133
136
|
"""Positive Net."""
|
|
137
|
+
from pyedb.grpc.database.net.net import Net
|
|
138
|
+
|
|
134
139
|
return Net(self._pedb, super().positive_net)
|
|
135
140
|
|
|
136
141
|
@property
|
|
137
142
|
def negative_net(self) -> Net:
|
|
138
143
|
"""Negative Net."""
|
|
144
|
+
from pyedb.grpc.database.net.net import Net
|
|
145
|
+
|
|
139
146
|
return Net(self._pedb, super().negative_net)
|
|
@@ -20,9 +20,13 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
from
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from pyedb.grpc.database.net.net import Net
|
|
29
|
+
from ansys.edb.core.net.extended_net import ExtendedNet as GrpcExtendedNet
|
|
26
30
|
|
|
27
31
|
|
|
28
32
|
class ExtendedNets:
|
|
@@ -204,12 +208,21 @@ class ExtendedNets:
|
|
|
204
208
|
val_value = cmp.rlc_values
|
|
205
209
|
if refdes in exception_list:
|
|
206
210
|
pass
|
|
207
|
-
elif cmp.type == "inductor"
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
elif cmp.type == "inductor":
|
|
212
|
+
if val_value[1] is None:
|
|
213
|
+
continue
|
|
214
|
+
elif not val_value[1] < inductor_below:
|
|
215
|
+
continue
|
|
216
|
+
elif cmp.type == "resistor":
|
|
217
|
+
if val_value[0] is None:
|
|
218
|
+
continue
|
|
219
|
+
elif not val_value[0] < resistor_below:
|
|
220
|
+
continue
|
|
221
|
+
elif cmp.type == "capacitor":
|
|
222
|
+
if val_value[2] is None:
|
|
223
|
+
continue
|
|
224
|
+
elif not val_value[2] > capacitor_above:
|
|
225
|
+
continue
|
|
213
226
|
else:
|
|
214
227
|
continue
|
|
215
228
|
for net in comp_dict[refdes]:
|
|
@@ -263,7 +276,7 @@ class ExtendedNet(GrpcExtendedNet):
|
|
|
263
276
|
self._pedb = pedb
|
|
264
277
|
|
|
265
278
|
@property
|
|
266
|
-
def nets(self):
|
|
279
|
+
def nets(self) -> dict[str, Net]:
|
|
267
280
|
"""Nets dictionary.
|
|
268
281
|
|
|
269
282
|
Returns
|
|
@@ -271,6 +284,8 @@ class ExtendedNet(GrpcExtendedNet):
|
|
|
271
284
|
Dict[str, :class:`Net <pyedb.grpc.database.net.net.Net>`]
|
|
272
285
|
Dict[net name, Net object].
|
|
273
286
|
"""
|
|
287
|
+
from pyedb.grpc.database.net.net import Net
|
|
288
|
+
|
|
274
289
|
return {net.name: Net(self._pedb, net) for net in super().nets}
|
|
275
290
|
|
|
276
291
|
@property
|
pyedb/grpc/database/net/net.py
CHANGED
|
@@ -20,14 +20,17 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
from
|
|
23
|
+
from __future__ import annotations
|
|
24
24
|
|
|
25
|
+
from typing import TYPE_CHECKING, Union
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from pyedb.grpc.database.primitive.circle import Circle
|
|
29
|
+
from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
25
30
|
from ansys.edb.core.net.net import Net as GrpcNet
|
|
26
31
|
from ansys.edb.core.primitive.primitive import PrimitiveType as GrpcPrimitiveType
|
|
27
32
|
|
|
28
33
|
from pyedb.grpc.database.primitive.bondwire import Bondwire
|
|
29
|
-
from pyedb.grpc.database.primitive.circle import Circle
|
|
30
|
-
from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
31
34
|
from pyedb.grpc.database.primitive.path import Path
|
|
32
35
|
from pyedb.grpc.database.primitive.polygon import Polygon
|
|
33
36
|
from pyedb.grpc.database.primitive.rectangle import Rectangle
|
|
@@ -76,6 +79,7 @@ class Net(GrpcNet):
|
|
|
76
79
|
- :class:`Rectangle <pyedb.grpc.database.primitive.rectangle.Rectangle>`
|
|
77
80
|
- :class:`Bondwire <pyedb.grpc.database.primitive.bondwire.Bondwire>`
|
|
78
81
|
"""
|
|
82
|
+
|
|
79
83
|
primitives = super().primitives
|
|
80
84
|
if not len(self.__primitives) == len(primitives):
|
|
81
85
|
for primitive in primitives:
|
|
@@ -100,6 +104,8 @@ class Net(GrpcNet):
|
|
|
100
104
|
list of :class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`
|
|
101
105
|
Padstack instances associated with the net.
|
|
102
106
|
"""
|
|
107
|
+
from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
108
|
+
|
|
103
109
|
return [PadstackInstance(self._pedb, i) for i in super().padstack_instances]
|
|
104
110
|
|
|
105
111
|
@property
|
|
@@ -118,8 +124,11 @@ class Net(GrpcNet):
|
|
|
118
124
|
if component:
|
|
119
125
|
try:
|
|
120
126
|
components[component.name] = component
|
|
121
|
-
except:
|
|
122
|
-
|
|
127
|
+
except Exception as e:
|
|
128
|
+
self._pedb.logger.error(
|
|
129
|
+
f"A(n) {type(e).__name__} error occurred while attempting to access "
|
|
130
|
+
f"'components' property for object {self} - Empty dict is returned: {str(e)}"
|
|
131
|
+
)
|
|
123
132
|
return components
|
|
124
133
|
|
|
125
134
|
def find_dc_short(self, fix=False) -> list[list[str, str]]:
|
|
@@ -20,9 +20,14 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
26
|
+
|
|
23
27
|
from ansys.edb.core.net.net_class import NetClass as GrpcNetClass
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from pyedb.grpc.database.net.net import Net
|
|
26
31
|
|
|
27
32
|
|
|
28
33
|
class NetClass(GrpcNetClass):
|
|
@@ -49,6 +54,8 @@ class NetClass(GrpcNetClass):
|
|
|
49
54
|
List[:class:`Net <pyedb.grpc.database.net.net.Net>`].
|
|
50
55
|
List of Net object.
|
|
51
56
|
"""
|
|
57
|
+
from pyedb.grpc.database.net.net import Net
|
|
58
|
+
|
|
52
59
|
return [Net(self._pedb, i) for i in super().nets]
|
|
53
60
|
|
|
54
61
|
def add_net(self, net):
|
|
@@ -59,21 +66,30 @@ class NetClass(GrpcNetClass):
|
|
|
59
66
|
bool
|
|
60
67
|
"""
|
|
61
68
|
if isinstance(net, str):
|
|
69
|
+
from pyedb.grpc.database.net.net import Net
|
|
70
|
+
|
|
62
71
|
net = Net.find_by_name(self._pedb.active_layout, name=net)
|
|
63
72
|
if isinstance(net, Net) and not net.is_null:
|
|
64
73
|
self.add_net(net)
|
|
65
74
|
return True
|
|
66
75
|
return False
|
|
67
76
|
|
|
68
|
-
def contains_net(self, net):
|
|
69
|
-
"""
|
|
77
|
+
def contains_net(self, net) -> bool:
|
|
78
|
+
"""
|
|
79
|
+
Determine if a net exists in the net class.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
net : str or Net
|
|
84
|
+
The net to check. This can be a string representing the net name or a `Net` object.
|
|
70
85
|
|
|
71
|
-
|
|
86
|
+
Returns
|
|
72
87
|
-------
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
bool
|
|
89
|
+
True if the net exists in the net class, False otherwise.
|
|
75
90
|
|
|
76
91
|
"""
|
|
92
|
+
|
|
77
93
|
if isinstance(net, str):
|
|
78
94
|
net = Net.find_by_name(self._pedb.active_layout, name=net)
|
|
79
95
|
return super().contains_net(net)
|
|
@@ -85,9 +101,10 @@ class NetClass(GrpcNetClass):
|
|
|
85
101
|
-------
|
|
86
102
|
bool
|
|
87
103
|
"""
|
|
104
|
+
|
|
88
105
|
if isinstance(net, str):
|
|
89
106
|
net = Net.find_by_name(self._pedb.active_layout, name=net)
|
|
90
107
|
if isinstance(net, Net) and not net.is_null:
|
|
91
|
-
self.
|
|
108
|
+
self.remove_net(net)
|
|
92
109
|
return True
|
|
93
110
|
return False
|
pyedb/grpc/database/nets.py
CHANGED
|
@@ -95,34 +95,21 @@ class Nets(CommonNets):
|
|
|
95
95
|
>>> print("Eligible power nets:", [net.name for net in eligible_pwr])
|
|
96
96
|
|
|
97
97
|
>>> # Generate extended nets (deprecated)
|
|
98
|
-
>>> nets.generate_extended_nets(
|
|
99
|
-
>>> resistor_below=5,
|
|
100
|
-
>>>inductor_below=0.5,
|
|
101
|
-
>>> capacitor_above=0.1
|
|
102
|
-
>>> )
|
|
98
|
+
>>> nets.generate_extended_nets(resistor_below=5, inductor_below=0.5, capacitor_above=0.1)
|
|
103
99
|
|
|
104
100
|
>>> # Classify nets
|
|
105
|
-
>>> nets.classify_nets(
|
|
106
|
-
>>> power_nets=["VDD_CPU", "VDD_MEM"],
|
|
107
|
-
>>> signal_nets=["PCIe_TX", "ETH_RX"]
|
|
108
|
-
>>> )
|
|
101
|
+
>>> nets.classify_nets(power_nets=["VDD_CPU", "VDD_MEM"], signal_nets=["PCIe_TX", "ETH_RX"])
|
|
109
102
|
|
|
110
103
|
>>> # Check power/ground status
|
|
111
104
|
>>> is_power = nets.is_power_gound_net(["VDD_CPU", "PCIe_TX"])
|
|
112
105
|
>>> print("Is power net:", is_power)
|
|
113
106
|
|
|
114
107
|
>>> # Get DC-connected nets
|
|
115
|
-
>>> dc_connected = nets.get_dcconnected_net_list(
|
|
116
|
-
>>> ground_nets=["GND"],
|
|
117
|
-
>>> res_value=0.002
|
|
118
|
-
>>> )
|
|
108
|
+
>>> dc_connected = nets.get_dcconnected_net_list(ground_nets=["GND"], res_value=0.002)
|
|
119
109
|
print("DC-connected nets:", dc_connected)
|
|
120
110
|
|
|
121
111
|
>>> # Get power tree
|
|
122
|
-
>>> comp_list, columns, net_group = nets.get_powertree(
|
|
123
|
-
>>> power_net_name="VDD_CPU",
|
|
124
|
-
>>> ground_nets=["GND"]
|
|
125
|
-
>>> )
|
|
112
|
+
>>> comp_list, columns, net_group = nets.get_powertree(power_net_name="VDD_CPU", ground_nets=["GND"])
|
|
126
113
|
>>> print("Power tree components:", comp_list)
|
|
127
114
|
|
|
128
115
|
>>> # Find net by name
|
|
@@ -142,10 +129,7 @@ class Nets(CommonNets):
|
|
|
142
129
|
>>> print("Net in component:", in_component)
|
|
143
130
|
|
|
144
131
|
>>> # Find and fix disjoint nets (deprecated)
|
|
145
|
-
>>> fixed_nets = nets.find_and_fix_disjoint_nets(
|
|
146
|
-
>>> net_list=["PCIe_TX"],
|
|
147
|
-
>>> clean_disjoints_less_than=1e-6
|
|
148
|
-
>>> )
|
|
132
|
+
>>> fixed_nets = nets.find_and_fix_disjoint_nets(net_list=["PCIe_TX"], clean_disjoints_less_than=1e-6)
|
|
149
133
|
>>> print("Fixed nets:", fixed_nets)
|
|
150
134
|
|
|
151
135
|
>>> # Merge net polygons
|
|
@@ -422,11 +406,7 @@ class Nets(CommonNets):
|
|
|
422
406
|
|
|
423
407
|
Examples
|
|
424
408
|
--------
|
|
425
|
-
>>> edb_nets.generate_extended_nets(
|
|
426
|
-
... resistor_below=5,
|
|
427
|
-
... inductor_below=0.5,
|
|
428
|
-
... capacitor_above=0.1
|
|
429
|
-
... )
|
|
409
|
+
>>> edb_nets.generate_extended_nets(resistor_below=5, inductor_below=0.5, capacitor_above=0.1)
|
|
430
410
|
"""
|
|
431
411
|
warnings.warn("Use new method :func:`edb.extended_nets.generate_extended_nets` instead.", DeprecationWarning)
|
|
432
412
|
self._pedb.extended_nets.generate_extended_nets(
|
|
@@ -487,10 +467,7 @@ class Nets(CommonNets):
|
|
|
487
467
|
|
|
488
468
|
Examples
|
|
489
469
|
--------
|
|
490
|
-
>>> edb_nets.classify_nets(
|
|
491
|
-
... power_nets=["VDD_CPU", "VDD_MEM"],
|
|
492
|
-
... signal_nets=["PCIe_TX", "ETH_RX"]
|
|
493
|
-
... )
|
|
470
|
+
>>> edb_nets.classify_nets(power_nets=["VDD_CPU", "VDD_MEM"], signal_nets=["PCIe_TX", "ETH_RX"])
|
|
494
471
|
"""
|
|
495
472
|
if isinstance(power_nets, str):
|
|
496
473
|
power_nets = []
|
|
@@ -551,10 +528,7 @@ class Nets(CommonNets):
|
|
|
551
528
|
|
|
552
529
|
Examples
|
|
553
530
|
--------
|
|
554
|
-
>>> dc_connected = edb_nets.get_dcconnected_net_list(
|
|
555
|
-
... ground_nets=["GND"],
|
|
556
|
-
... res_value=0.002
|
|
557
|
-
... )
|
|
531
|
+
>>> dc_connected = edb_nets.get_dcconnected_net_list(ground_nets=["GND"], res_value=0.002)
|
|
558
532
|
>>> for net_group in dc_connected:
|
|
559
533
|
... print("Connected nets:", net_group)
|
|
560
534
|
"""
|
|
@@ -611,10 +585,7 @@ class Nets(CommonNets):
|
|
|
611
585
|
|
|
612
586
|
Examples
|
|
613
587
|
--------
|
|
614
|
-
>>> comp_list, columns, net_group = edb_nets.get_powertree(
|
|
615
|
-
... power_net_name="VDD_CPU",
|
|
616
|
-
... ground_nets=["GND"]
|
|
617
|
-
... )
|
|
588
|
+
>>> comp_list, columns, net_group = edb_nets.get_powertree(power_net_name="VDD_CPU", ground_nets=["GND"])
|
|
618
589
|
>>> print("Power tree components:", comp_list)
|
|
619
590
|
"""
|
|
620
591
|
flag_in_ng = False
|
|
@@ -700,7 +671,7 @@ class Nets(CommonNets):
|
|
|
700
671
|
|
|
701
672
|
Examples
|
|
702
673
|
--------
|
|
703
|
-
>>> deleted_nets = database.nets.delete(["Net1","Net2"])
|
|
674
|
+
>>> deleted_nets = database.nets.delete(["Net1", "Net2"])
|
|
704
675
|
"""
|
|
705
676
|
if isinstance(netlist, str):
|
|
706
677
|
netlist = [netlist]
|
|
@@ -858,10 +829,7 @@ class Nets(CommonNets):
|
|
|
858
829
|
|
|
859
830
|
Examples
|
|
860
831
|
--------
|
|
861
|
-
>>> fixed_nets = edb_nets.find_and_fix_disjoint_nets(
|
|
862
|
-
... net_list=["PCIe_TX"],
|
|
863
|
-
... clean_disjoints_less_than=1e-6
|
|
864
|
-
... )
|
|
832
|
+
>>> fixed_nets = edb_nets.find_and_fix_disjoint_nets(net_list=["PCIe_TX"], clean_disjoints_less_than=1e-6)
|
|
865
833
|
>>> print("Fixed nets:", fixed_nets)
|
|
866
834
|
"""
|
|
867
835
|
|
pyedb/grpc/database/padstacks.py
CHANGED
|
@@ -23,27 +23,21 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains the `EdbPadstacks` class.
|
|
25
25
|
"""
|
|
26
|
+
|
|
26
27
|
from collections import defaultdict
|
|
28
|
+
from functools import lru_cache
|
|
27
29
|
import math
|
|
28
30
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
29
31
|
import warnings
|
|
30
32
|
|
|
31
33
|
from ansys.edb.core.definition.padstack_def_data import (
|
|
32
34
|
PadGeometryType as GrpcPadGeometryType,
|
|
33
|
-
)
|
|
34
|
-
from ansys.edb.core.definition.padstack_def_data import (
|
|
35
35
|
PadstackDefData as GrpcPadstackDefData,
|
|
36
|
-
)
|
|
37
|
-
from ansys.edb.core.definition.padstack_def_data import (
|
|
38
36
|
PadstackHoleRange as GrpcPadstackHoleRange,
|
|
39
|
-
|
|
40
|
-
from ansys.edb.core.definition.padstack_def_data import (
|
|
37
|
+
PadType as GrpcPadType,
|
|
41
38
|
SolderballPlacement as GrpcSolderballPlacement,
|
|
42
|
-
)
|
|
43
|
-
from ansys.edb.core.definition.padstack_def_data import (
|
|
44
39
|
SolderballShape as GrpcSolderballShape,
|
|
45
40
|
)
|
|
46
|
-
from ansys.edb.core.definition.padstack_def_data import PadType as GrpcPadType
|
|
47
41
|
from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
|
|
48
42
|
from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
|
|
49
43
|
import numpy as np
|
|
@@ -55,6 +49,29 @@ from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
|
55
49
|
from pyedb.grpc.database.utility.value import Value
|
|
56
50
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
57
51
|
|
|
52
|
+
GEOMETRY_MAP = {
|
|
53
|
+
0: GrpcPadGeometryType.PADGEOMTYPE_NO_GEOMETRY,
|
|
54
|
+
1: GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
55
|
+
2: GrpcPadGeometryType.PADGEOMTYPE_SQUARE,
|
|
56
|
+
3: GrpcPadGeometryType.PADGEOMTYPE_RECTANGLE,
|
|
57
|
+
4: GrpcPadGeometryType.PADGEOMTYPE_OVAL,
|
|
58
|
+
5: GrpcPadGeometryType.PADGEOMTYPE_BULLET,
|
|
59
|
+
6: GrpcPadGeometryType.PADGEOMTYPE_NSIDED_POLYGON,
|
|
60
|
+
7: GrpcPadGeometryType.PADGEOMTYPE_POLYGON,
|
|
61
|
+
8: GrpcPadGeometryType.PADGEOMTYPE_ROUND45,
|
|
62
|
+
9: GrpcPadGeometryType.PADGEOMTYPE_ROUND90,
|
|
63
|
+
10: GrpcPadGeometryType.PADGEOMTYPE_SQUARE45,
|
|
64
|
+
11: GrpcPadGeometryType.PADGEOMTYPE_SQUARE90,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
PAD_TYPE_MAP = {
|
|
68
|
+
0: GrpcPadType.REGULAR_PAD,
|
|
69
|
+
1: GrpcPadType.ANTI_PAD,
|
|
70
|
+
2: GrpcPadType.THERMAL_PAD,
|
|
71
|
+
3: GrpcPadType.HOLE,
|
|
72
|
+
4: GrpcPadType.UNKNOWN_GEOM_TYPE,
|
|
73
|
+
}
|
|
74
|
+
|
|
58
75
|
|
|
59
76
|
class Padstacks(object):
|
|
60
77
|
"""Manages EDB methods for padstacks accessible from `Edb.padstacks` property.
|
|
@@ -94,6 +111,15 @@ class Padstacks(object):
|
|
|
94
111
|
def __init__(self, p_edb: Any) -> None:
|
|
95
112
|
self._pedb = p_edb
|
|
96
113
|
self.__definitions: Dict[str, Any] = {}
|
|
114
|
+
self._instances = None
|
|
115
|
+
self._instances_by_name = {}
|
|
116
|
+
self._instances_by_net = {}
|
|
117
|
+
|
|
118
|
+
def clear_instances_cache(self):
|
|
119
|
+
"""Clear the cached padstack instances."""
|
|
120
|
+
self._instances = None
|
|
121
|
+
self._instances_by_name = {}
|
|
122
|
+
self._instances_by_net = {}
|
|
97
123
|
|
|
98
124
|
@property
|
|
99
125
|
def _active_layout(self) -> Any:
|
|
@@ -120,7 +146,8 @@ class Padstacks(object):
|
|
|
120
146
|
""" """
|
|
121
147
|
return self._pedb.stackup.layers
|
|
122
148
|
|
|
123
|
-
|
|
149
|
+
@staticmethod
|
|
150
|
+
def int_to_pad_type(val=0) -> GrpcPadType:
|
|
124
151
|
"""Convert an integer to an EDB.PadGeometryType.
|
|
125
152
|
|
|
126
153
|
Parameters
|
|
@@ -138,20 +165,10 @@ class Padstacks(object):
|
|
|
138
165
|
>>> pad_type = edb_padstacks.int_to_pad_type(1) # Returns ANTI_PAD
|
|
139
166
|
"""
|
|
140
167
|
|
|
141
|
-
|
|
142
|
-
return GrpcPadType.REGULAR_PAD
|
|
143
|
-
elif val == 1:
|
|
144
|
-
return GrpcPadType.ANTI_PAD
|
|
145
|
-
elif val == 2:
|
|
146
|
-
return GrpcPadType.THERMAL_PAD
|
|
147
|
-
elif val == 3:
|
|
148
|
-
return GrpcPadType.HOLE
|
|
149
|
-
elif val == 4:
|
|
150
|
-
return GrpcPadType.UNKNOWN_GEOM_TYPE
|
|
151
|
-
else:
|
|
152
|
-
return val
|
|
168
|
+
return PAD_TYPE_MAP.get(val, val)
|
|
153
169
|
|
|
154
|
-
|
|
170
|
+
@staticmethod
|
|
171
|
+
def int_to_geometry_type(val: int = 0) -> GrpcPadGeometryType:
|
|
155
172
|
"""Convert an integer to an EDB.PadGeometryType.
|
|
156
173
|
|
|
157
174
|
Parameters
|
|
@@ -168,32 +185,7 @@ class Padstacks(object):
|
|
|
168
185
|
>>> geom_type = edb_padstacks.int_to_geometry_type(1) # Returns CIRCLE
|
|
169
186
|
>>> geom_type = edb_padstacks.int_to_geometry_type(2) # Returns SQUARE
|
|
170
187
|
"""
|
|
171
|
-
|
|
172
|
-
return GrpcPadGeometryType.PADGEOMTYPE_NO_GEOMETRY
|
|
173
|
-
elif val == 1:
|
|
174
|
-
return GrpcPadGeometryType.PADGEOMTYPE_CIRCLE
|
|
175
|
-
elif val == 2:
|
|
176
|
-
return GrpcPadGeometryType.PADGEOMTYPE_SQUARE
|
|
177
|
-
elif val == 3:
|
|
178
|
-
return GrpcPadGeometryType.PADGEOMTYPE_RECTANGLE
|
|
179
|
-
elif val == 4:
|
|
180
|
-
return GrpcPadGeometryType.PADGEOMTYPE_OVAL
|
|
181
|
-
elif val == 5:
|
|
182
|
-
return GrpcPadGeometryType.PADGEOMTYPE_BULLET
|
|
183
|
-
elif val == 6:
|
|
184
|
-
return GrpcPadGeometryType.PADGEOMTYPE_NSIDED_POLYGON
|
|
185
|
-
elif val == 7:
|
|
186
|
-
return GrpcPadGeometryType.PADGEOMTYPE_POLYGON
|
|
187
|
-
elif val == 8:
|
|
188
|
-
return GrpcPadGeometryType.PADGEOMTYPE_ROUND45
|
|
189
|
-
elif val == 9:
|
|
190
|
-
return GrpcPadGeometryType.PADGEOMTYPE_ROUND90
|
|
191
|
-
elif val == 10:
|
|
192
|
-
return GrpcPadGeometryType.PADGEOMTYPE_SQUARE45
|
|
193
|
-
elif val == 11:
|
|
194
|
-
return GrpcPadGeometryType.PADGEOMTYPE_SQUARE90
|
|
195
|
-
else:
|
|
196
|
-
return val
|
|
188
|
+
return GEOMETRY_MAP.get(val, val)
|
|
197
189
|
|
|
198
190
|
@property
|
|
199
191
|
def definitions(self) -> Dict[str, PadstackDef]:
|
|
@@ -232,7 +224,17 @@ class Padstacks(object):
|
|
|
232
224
|
>>> for id, instance in all_instances.items():
|
|
233
225
|
... print(f"Instance {id}: {instance.name}")
|
|
234
226
|
"""
|
|
235
|
-
|
|
227
|
+
if self._instances is None:
|
|
228
|
+
self._instances = self._pedb.layout.padstack_instances
|
|
229
|
+
return self._instances
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def instances_by_net(self) -> Dict[Any, PadstackInstance]:
|
|
233
|
+
if not self._instances_by_net:
|
|
234
|
+
for edb_padstack_instance in self._instances.values():
|
|
235
|
+
if edb_padstack_instance.net_name:
|
|
236
|
+
self._instances_by_net.setdefault(edb_padstack_instance.net_name, []).append(edb_padstack_instance)
|
|
237
|
+
return self._instances_by_net
|
|
236
238
|
|
|
237
239
|
@property
|
|
238
240
|
def instances_by_name(self) -> Dict[str, PadstackInstance]:
|
|
@@ -249,11 +251,11 @@ class Padstacks(object):
|
|
|
249
251
|
>>> for name, instance in named_instances.items():
|
|
250
252
|
... print(f"Instance named {name}")
|
|
251
253
|
"""
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
return
|
|
254
|
+
if not self._instances_by_name:
|
|
255
|
+
for _, edb_padstack_instance in self.instances.items():
|
|
256
|
+
if edb_padstack_instance.aedt_name:
|
|
257
|
+
self._instances_by_name[edb_padstack_instance.aedt_name] = edb_padstack_instance
|
|
258
|
+
return self._instances_by_name
|
|
257
259
|
|
|
258
260
|
def find_instance_by_id(self, value: int) -> Optional[PadstackInstance]:
|
|
259
261
|
"""Find a padstack instance by database ID.
|
|
@@ -334,7 +336,7 @@ class Padstacks(object):
|
|
|
334
336
|
>>> groups = edb_padstacks._layout.pin_groups # New way
|
|
335
337
|
"""
|
|
336
338
|
warnings.warn(
|
|
337
|
-
"`pingroups` is deprecated and is now located here
|
|
339
|
+
"`pingroups` is deprecated and is now located here `pyedb.grpc.core.layout.pin_groups` instead.",
|
|
338
340
|
DeprecationWarning,
|
|
339
341
|
)
|
|
340
342
|
return self._layout.pin_groups
|
|
@@ -380,10 +382,7 @@ class Padstacks(object):
|
|
|
380
382
|
Examples
|
|
381
383
|
--------
|
|
382
384
|
>>> via_name = edb_padstacks.create_circular_padstack(
|
|
383
|
-
... padstackname="VIA1",
|
|
384
|
-
... holediam="200um",
|
|
385
|
-
... paddiam="400um",
|
|
386
|
-
... antipaddiam="600um"
|
|
385
|
+
... padstackname="VIA1", holediam="200um", paddiam="400um", antipaddiam="600um"
|
|
387
386
|
... )
|
|
388
387
|
"""
|
|
389
388
|
|
|
@@ -481,6 +480,7 @@ class Padstacks(object):
|
|
|
481
480
|
if p.net_name in net_names:
|
|
482
481
|
if not p.delete(): # pragma: no cover
|
|
483
482
|
return False
|
|
483
|
+
self.clear_instances_cache()
|
|
484
484
|
return True
|
|
485
485
|
|
|
486
486
|
def set_solderball(self, padstackInst, sballLayer_name, isTopPlaced=True, ballDiam=100e-6):
|
|
@@ -1143,6 +1143,7 @@ class Padstacks(object):
|
|
|
1143
1143
|
layer_map=None,
|
|
1144
1144
|
)
|
|
1145
1145
|
padstack_instance.is_layout_pin = is_pin
|
|
1146
|
+
self.clear_instances_cache()
|
|
1146
1147
|
return PadstackInstance(self._pedb, padstack_instance)
|
|
1147
1148
|
else:
|
|
1148
1149
|
raise RuntimeError("Place padstack failed")
|
|
@@ -1299,8 +1300,7 @@ class Padstacks(object):
|
|
|
1299
1300
|
List of padstack instances associated with the specified net.
|
|
1300
1301
|
"""
|
|
1301
1302
|
warnings.warn(
|
|
1302
|
-
"`get_padstack_instance_by_net_name` is deprecated, use `get_instances` with `net_name` "
|
|
1303
|
-
"parameter instead.",
|
|
1303
|
+
"`get_padstack_instance_by_net_name` is deprecated, use `get_instances` with `net_name` parameter instead.",
|
|
1304
1304
|
DeprecationWarning,
|
|
1305
1305
|
)
|
|
1306
1306
|
return self.get_instances(net_name=net)
|
|
@@ -1516,7 +1516,7 @@ class Padstacks(object):
|
|
|
1516
1516
|
minimum_via_number: int = 6,
|
|
1517
1517
|
selected_angles: Optional[List[float]] = None,
|
|
1518
1518
|
padstack_instances_id: Optional[List[int]] = None,
|
|
1519
|
-
) ->
|
|
1519
|
+
) -> List[str]:
|
|
1520
1520
|
"""Replace padstack instances along lines into a single polygon.
|
|
1521
1521
|
|
|
1522
1522
|
Detect all pad-stack instances that are placed along lines and replace them by a single polygon based one
|
|
@@ -1605,66 +1605,13 @@ class Padstacks(object):
|
|
|
1605
1605
|
inst.delete()
|
|
1606
1606
|
return instances_created
|
|
1607
1607
|
|
|
1608
|
-
def reduce_via_in_bounding_box(self, bounding_box, x_samples, y_samples, nets=None):
|
|
1609
|
-
"""Reduces the number of vias intersecting bounding box and nets by x and y samples.
|
|
1610
|
-
|
|
1611
|
-
Parameters
|
|
1612
|
-
----------
|
|
1613
|
-
bounding_box : tuple or list.
|
|
1614
|
-
bounding box, [x1, y1, x2, y2]
|
|
1615
|
-
x_samples : int
|
|
1616
|
-
y_samples : int
|
|
1617
|
-
nets : str or list, optional
|
|
1618
|
-
net name or list of nets name applying filtering on padstack instances selection. If ``None`` is provided
|
|
1619
|
-
all instances are included in the index. Default value is ``None``.
|
|
1620
|
-
|
|
1621
|
-
Returns
|
|
1622
|
-
-------
|
|
1623
|
-
bool
|
|
1624
|
-
``True`` when succeeded ``False`` when failed.
|
|
1625
|
-
"""
|
|
1626
|
-
|
|
1627
|
-
padstacks_inbox = self.get_padstack_instances_intersecting_bounding_box(bounding_box, nets)
|
|
1628
|
-
if not padstacks_inbox:
|
|
1629
|
-
self._logger.info("no padstack in bounding box")
|
|
1630
|
-
return False
|
|
1631
|
-
else:
|
|
1632
|
-
if len(padstacks_inbox) <= (x_samples * y_samples):
|
|
1633
|
-
self._logger.info(f"more samples {x_samples * y_samples} than existing {len(padstacks_inbox)}")
|
|
1634
|
-
return False
|
|
1635
|
-
else:
|
|
1636
|
-
# extract ids and positions
|
|
1637
|
-
vias = {item: self.instances[item].position for item in padstacks_inbox}
|
|
1638
|
-
ids, positions = zip(*vias.items())
|
|
1639
|
-
pt_x, pt_y = zip(*positions)
|
|
1640
|
-
|
|
1641
|
-
# meshgrid
|
|
1642
|
-
_x_min, _x_max = min(pt_x), max(pt_x)
|
|
1643
|
-
_y_min, _y_max = min(pt_y), max(pt_y)
|
|
1644
|
-
|
|
1645
|
-
x_grid, y_grid = np.meshgrid(
|
|
1646
|
-
np.linspace(_x_min, _x_max, x_samples), np.linspace(_y_min, _y_max, y_samples)
|
|
1647
|
-
)
|
|
1648
|
-
|
|
1649
|
-
# mapping to meshgrid
|
|
1650
|
-
to_keep = {
|
|
1651
|
-
ids[np.argmin(np.square(_x - pt_x) + np.square(_y - pt_y))]
|
|
1652
|
-
for _x, _y in zip(x_grid.ravel(), y_grid.ravel())
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
for item in padstacks_inbox:
|
|
1656
|
-
if item not in to_keep:
|
|
1657
|
-
self.instances[item].delete()
|
|
1658
|
-
|
|
1659
|
-
return True
|
|
1660
|
-
|
|
1661
1608
|
def merge_via(
|
|
1662
1609
|
self,
|
|
1663
1610
|
contour_boxes: List[List[float]],
|
|
1664
1611
|
net_filter: Optional[Union[str, List[str]]] = None,
|
|
1665
1612
|
start_layer: Optional[str] = None,
|
|
1666
1613
|
stop_layer: Optional[str] = None,
|
|
1667
|
-
) ->
|
|
1614
|
+
) -> List[str]:
|
|
1668
1615
|
"""Evaluate pad-stack instances included on the provided point list and replace all by single instance.
|
|
1669
1616
|
|
|
1670
1617
|
Parameters
|
|
@@ -1684,7 +1631,6 @@ class Padstacks(object):
|
|
|
1684
1631
|
|
|
1685
1632
|
"""
|
|
1686
1633
|
|
|
1687
|
-
import numpy as np
|
|
1688
1634
|
from scipy.spatial import ConvexHull
|
|
1689
1635
|
|
|
1690
1636
|
merged_via_ids = []
|
|
@@ -1728,6 +1674,7 @@ class Padstacks(object):
|
|
|
1728
1674
|
)
|
|
1729
1675
|
merged_via_ids.append(merged_instance.edb_uid)
|
|
1730
1676
|
[self.instances[inst].delete() for inst in instances]
|
|
1677
|
+
self.clear_instances_cache()
|
|
1731
1678
|
return merged_via_ids
|
|
1732
1679
|
|
|
1733
1680
|
def reduce_via_in_bounding_box(
|
|
@@ -1783,6 +1730,7 @@ class Padstacks(object):
|
|
|
1783
1730
|
for item in padstacks_inbox:
|
|
1784
1731
|
if item not in to_keep:
|
|
1785
1732
|
all_instances[item].delete()
|
|
1733
|
+
self.clear_instances_cache()
|
|
1786
1734
|
return True
|
|
1787
1735
|
|
|
1788
1736
|
@staticmethod
|
|
@@ -1938,5 +1886,5 @@ class Padstacks(object):
|
|
|
1938
1886
|
to_delete = set(padstacks) - to_keep
|
|
1939
1887
|
for _id in to_delete:
|
|
1940
1888
|
all_instances[_id].delete()
|
|
1941
|
-
|
|
1889
|
+
self.clear_instances_cache()
|
|
1942
1890
|
return list(to_keep), grid
|