pyedb 0.53.0__py3-none-any.whl → 0.55.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 -8
- pyedb/configuration/cfg_boundaries.py +69 -151
- pyedb/configuration/cfg_components.py +201 -460
- pyedb/configuration/cfg_data.py +4 -2
- pyedb/configuration/cfg_general.py +13 -36
- pyedb/configuration/cfg_modeler.py +2 -1
- pyedb/configuration/cfg_nets.py +21 -35
- pyedb/configuration/cfg_operations.py +22 -151
- pyedb/configuration/cfg_package_definition.py +56 -112
- pyedb/configuration/cfg_padstacks.py +292 -688
- pyedb/configuration/cfg_pin_groups.py +32 -79
- pyedb/configuration/cfg_ports_sources.py +20 -9
- pyedb/configuration/cfg_s_parameter_models.py +67 -172
- pyedb/configuration/cfg_setup.py +102 -295
- pyedb/configuration/configuration.py +66 -6
- pyedb/dotnet/database/cell/connectable.py +38 -9
- pyedb/dotnet/database/cell/hierarchy/component.py +28 -28
- pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
- pyedb/dotnet/database/cell/layout.py +64 -3
- pyedb/dotnet/database/cell/layout_obj.py +3 -3
- pyedb/dotnet/database/cell/primitive/path.py +6 -8
- pyedb/dotnet/database/cell/primitive/primitive.py +10 -31
- pyedb/dotnet/database/cell/terminal/edge_terminal.py +2 -2
- pyedb/dotnet/database/cell/terminal/padstack_instance_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +26 -28
- pyedb/dotnet/database/cell/voltage_regulator.py +0 -21
- pyedb/dotnet/database/components.py +99 -91
- pyedb/dotnet/database/definition/component_def.py +4 -4
- pyedb/dotnet/database/definition/component_model.py +1 -1
- pyedb/dotnet/database/definition/package_def.py +2 -3
- pyedb/dotnet/database/dotnet/database.py +27 -218
- pyedb/dotnet/database/dotnet/primitive.py +16 -16
- pyedb/dotnet/database/edb_data/control_file.py +5 -5
- pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
- pyedb/dotnet/database/edb_data/layer_data.py +35 -35
- pyedb/dotnet/database/edb_data/padstacks_data.py +65 -90
- pyedb/dotnet/database/edb_data/primitives_data.py +5 -5
- pyedb/dotnet/database/edb_data/sources.py +6 -6
- pyedb/dotnet/database/edb_data/variables.py +8 -4
- pyedb/dotnet/database/geometry/point_data.py +14 -10
- pyedb/dotnet/database/geometry/polygon_data.py +3 -5
- pyedb/dotnet/database/hfss.py +50 -52
- pyedb/dotnet/database/layout_validation.py +14 -11
- pyedb/dotnet/database/materials.py +10 -11
- pyedb/dotnet/database/modeler.py +104 -101
- pyedb/dotnet/database/nets.py +20 -23
- pyedb/dotnet/database/padstack.py +156 -84
- pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
- pyedb/dotnet/database/siwave.py +47 -47
- pyedb/dotnet/database/stackup.py +152 -87
- pyedb/dotnet/database/utilities/heatsink.py +4 -4
- pyedb/dotnet/database/utilities/obj_base.py +3 -3
- pyedb/dotnet/database/utilities/simulation_setup.py +2 -2
- pyedb/dotnet/database/utilities/value.py +116 -0
- pyedb/dotnet/edb.py +248 -170
- pyedb/edb_logger.py +12 -27
- pyedb/extensions/via_design_backend.py +6 -3
- pyedb/generic/design_types.py +68 -21
- pyedb/generic/general_methods.py +0 -120
- pyedb/generic/process.py +44 -108
- pyedb/generic/settings.py +75 -19
- pyedb/grpc/__init__.py +0 -0
- pyedb/grpc/database/components.py +55 -17
- pyedb/grpc/database/control_file.py +5 -5
- pyedb/grpc/database/definition/materials.py +24 -31
- pyedb/grpc/database/definition/package_def.py +18 -18
- pyedb/grpc/database/definition/padstack_def.py +104 -51
- pyedb/grpc/database/geometry/arc_data.py +7 -5
- pyedb/grpc/database/geometry/point_3d_data.py +8 -7
- pyedb/grpc/database/geometry/polygon_data.py +4 -3
- pyedb/grpc/database/hierarchy/component.py +43 -38
- pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
- pyedb/grpc/database/hierarchy/pingroup.py +9 -9
- pyedb/grpc/database/layers/stackup_layer.py +45 -44
- pyedb/grpc/database/layout/layout.py +17 -13
- pyedb/grpc/database/layout/voltage_regulator.py +7 -7
- pyedb/grpc/database/layout_validation.py +16 -15
- pyedb/grpc/database/modeler.py +60 -58
- pyedb/grpc/database/net/net.py +15 -14
- pyedb/grpc/database/nets.py +112 -31
- pyedb/grpc/database/padstacks.py +303 -190
- pyedb/grpc/database/ports/ports.py +5 -6
- pyedb/grpc/database/primitive/bondwire.py +8 -7
- pyedb/grpc/database/primitive/circle.py +4 -4
- pyedb/grpc/database/primitive/padstack_instance.py +191 -23
- pyedb/grpc/database/primitive/path.py +7 -7
- pyedb/grpc/database/primitive/polygon.py +3 -3
- pyedb/grpc/database/primitive/primitive.py +13 -17
- pyedb/grpc/database/primitive/rectangle.py +13 -13
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
- pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
- pyedb/grpc/database/siwave.py +31 -25
- pyedb/grpc/database/source_excitations.py +335 -233
- pyedb/grpc/database/stackup.py +165 -148
- pyedb/grpc/database/terminal/bundle_terminal.py +18 -8
- pyedb/grpc/database/terminal/edge_terminal.py +10 -0
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +16 -5
- pyedb/grpc/database/terminal/pingroup_terminal.py +12 -11
- pyedb/grpc/database/terminal/point_terminal.py +4 -3
- pyedb/grpc/database/terminal/terminal.py +9 -9
- pyedb/grpc/database/utility/value.py +109 -0
- pyedb/grpc/database/utility/xml_control_file.py +5 -5
- pyedb/grpc/edb.py +130 -63
- pyedb/grpc/edb_init.py +3 -10
- pyedb/grpc/rpc_session.py +10 -10
- pyedb/libraries/common.py +366 -0
- pyedb/libraries/rf_libraries/base_functions.py +1358 -0
- pyedb/libraries/rf_libraries/planar_antennas.py +628 -0
- pyedb/misc/decorators.py +61 -0
- pyedb/misc/misc.py +0 -13
- pyedb/siwave.py +2 -2
- {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/METADATA +2 -3
- {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/RECORD +119 -112
- {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/WHEEL +0 -0
- {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/licenses/LICENSE +0 -0
pyedb/grpc/database/padstacks.py
CHANGED
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"""
|
|
24
24
|
This module contains the `EdbPadstacks` class.
|
|
25
25
|
"""
|
|
26
|
+
from collections import defaultdict
|
|
26
27
|
import math
|
|
28
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
27
29
|
import warnings
|
|
28
30
|
|
|
29
31
|
from ansys.edb.core.definition.padstack_def_data import (
|
|
@@ -44,13 +46,13 @@ from ansys.edb.core.definition.padstack_def_data import (
|
|
|
44
46
|
from ansys.edb.core.definition.padstack_def_data import PadType as GrpcPadType
|
|
45
47
|
from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
|
|
46
48
|
from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
|
|
47
|
-
from ansys.edb.core.utility.value import Value as GrpcValue
|
|
48
49
|
import numpy as np
|
|
49
50
|
import rtree
|
|
50
51
|
|
|
51
52
|
from pyedb.generic.general_methods import generate_unique_name
|
|
52
53
|
from pyedb.grpc.database.definition.padstack_def import PadstackDef
|
|
53
54
|
from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
|
|
55
|
+
from pyedb.grpc.database.utility.value import Value
|
|
54
56
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
55
57
|
|
|
56
58
|
|
|
@@ -89,37 +91,36 @@ class Padstacks(object):
|
|
|
89
91
|
self._pedb.logger.error("Component or definition not found.")
|
|
90
92
|
return
|
|
91
93
|
|
|
92
|
-
def __init__(self, p_edb):
|
|
94
|
+
def __init__(self, p_edb: Any) -> None:
|
|
93
95
|
self._pedb = p_edb
|
|
94
|
-
self.
|
|
95
|
-
self._definitions = {}
|
|
96
|
+
self.__definitions: Dict[str, Any] = {}
|
|
96
97
|
|
|
97
98
|
@property
|
|
98
|
-
def _active_layout(self):
|
|
99
|
+
def _active_layout(self) -> Any:
|
|
99
100
|
""" """
|
|
100
101
|
return self._pedb.active_layout
|
|
101
102
|
|
|
102
103
|
@property
|
|
103
|
-
def _layout(self):
|
|
104
|
+
def _layout(self) -> Any:
|
|
104
105
|
""" """
|
|
105
106
|
return self._pedb.layout
|
|
106
107
|
|
|
107
108
|
@property
|
|
108
|
-
def db(self):
|
|
109
|
+
def db(self) -> Any:
|
|
109
110
|
"""Db object."""
|
|
110
111
|
return self._pedb.active_db
|
|
111
112
|
|
|
112
113
|
@property
|
|
113
|
-
def _logger(self):
|
|
114
|
+
def _logger(self) -> Any:
|
|
114
115
|
""" """
|
|
115
116
|
return self._pedb.logger
|
|
116
117
|
|
|
117
118
|
@property
|
|
118
|
-
def _layers(self):
|
|
119
|
+
def _layers(self) -> Any:
|
|
119
120
|
""" """
|
|
120
121
|
return self._pedb.stackup.layers
|
|
121
122
|
|
|
122
|
-
def int_to_pad_type(self, val=0):
|
|
123
|
+
def int_to_pad_type(self, val=0) -> GrpcPadType:
|
|
123
124
|
"""Convert an integer to an EDB.PadGeometryType.
|
|
124
125
|
|
|
125
126
|
Parameters
|
|
@@ -150,7 +151,7 @@ class Padstacks(object):
|
|
|
150
151
|
else:
|
|
151
152
|
return val
|
|
152
153
|
|
|
153
|
-
def int_to_geometry_type(self, val=0):
|
|
154
|
+
def int_to_geometry_type(self, val: int = 0) -> GrpcPadGeometryType:
|
|
154
155
|
"""Convert an integer to an EDB.PadGeometryType.
|
|
155
156
|
|
|
156
157
|
Parameters
|
|
@@ -195,7 +196,7 @@ class Padstacks(object):
|
|
|
195
196
|
return val
|
|
196
197
|
|
|
197
198
|
@property
|
|
198
|
-
def definitions(self):
|
|
199
|
+
def definitions(self) -> Dict[str, PadstackDef]:
|
|
199
200
|
"""Padstack definitions.
|
|
200
201
|
|
|
201
202
|
Returns
|
|
@@ -209,16 +210,15 @@ class Padstacks(object):
|
|
|
209
210
|
>>> for name, definition in all_definitions.items():
|
|
210
211
|
... print(f"Padstack: {name}")
|
|
211
212
|
"""
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
for padstack_def in self._pedb.db.padstack_defs:
|
|
213
|
+
padstack_defs = self._pedb.db.padstack_defs
|
|
214
|
+
self.__definitions = {}
|
|
215
|
+
for padstack_def in padstack_defs:
|
|
216
216
|
if len(padstack_def.data.layer_names) >= 1:
|
|
217
|
-
self.
|
|
218
|
-
return self.
|
|
217
|
+
self.__definitions[padstack_def.name] = PadstackDef(self._pedb, padstack_def)
|
|
218
|
+
return self.__definitions
|
|
219
219
|
|
|
220
220
|
@property
|
|
221
|
-
def instances(self):
|
|
221
|
+
def instances(self) -> Dict[int, PadstackInstance]:
|
|
222
222
|
"""All padstack instances (vias and pins) in the layout.
|
|
223
223
|
|
|
224
224
|
Returns
|
|
@@ -228,18 +228,14 @@ class Padstacks(object):
|
|
|
228
228
|
|
|
229
229
|
Examples
|
|
230
230
|
--------
|
|
231
|
-
>>> all_instances =
|
|
231
|
+
>>> all_instances = edb.padstacks.instances
|
|
232
232
|
>>> for id, instance in all_instances.items():
|
|
233
233
|
... print(f"Instance {id}: {instance.name}")
|
|
234
234
|
"""
|
|
235
|
-
|
|
236
|
-
if len(self._instances) == len(pad_stack_inst):
|
|
237
|
-
return self._instances
|
|
238
|
-
self._instances = {i.edb_uid: PadstackInstance(self._pedb, i) for i in pad_stack_inst}
|
|
239
|
-
return self._instances
|
|
235
|
+
return self._pedb.layout.padstack_instances
|
|
240
236
|
|
|
241
237
|
@property
|
|
242
|
-
def instances_by_name(self):
|
|
238
|
+
def instances_by_name(self) -> Dict[str, PadstackInstance]:
|
|
243
239
|
"""All padstack instances (vias and pins) indexed by name.
|
|
244
240
|
|
|
245
241
|
Returns
|
|
@@ -259,7 +255,7 @@ class Padstacks(object):
|
|
|
259
255
|
padstack_instances[edb_padstack_instance.aedt_name] = edb_padstack_instance
|
|
260
256
|
return padstack_instances
|
|
261
257
|
|
|
262
|
-
def find_instance_by_id(self, value: int):
|
|
258
|
+
def find_instance_by_id(self, value: int) -> Optional[PadstackInstance]:
|
|
263
259
|
"""Find a padstack instance by database ID.
|
|
264
260
|
|
|
265
261
|
Parameters
|
|
@@ -281,7 +277,7 @@ class Padstacks(object):
|
|
|
281
277
|
return self._pedb.modeler.find_object_by_id(value)
|
|
282
278
|
|
|
283
279
|
@property
|
|
284
|
-
def pins(self):
|
|
280
|
+
def pins(self) -> Dict[int, PadstackInstance]:
|
|
285
281
|
"""All pin instances belonging to components.
|
|
286
282
|
|
|
287
283
|
Returns
|
|
@@ -302,7 +298,7 @@ class Padstacks(object):
|
|
|
302
298
|
return pins
|
|
303
299
|
|
|
304
300
|
@property
|
|
305
|
-
def vias(self):
|
|
301
|
+
def vias(self) -> Dict[int, PadstackInstance]:
|
|
306
302
|
"""All via instances not belonging to components.
|
|
307
303
|
|
|
308
304
|
Returns
|
|
@@ -321,7 +317,7 @@ class Padstacks(object):
|
|
|
321
317
|
return vias
|
|
322
318
|
|
|
323
319
|
@property
|
|
324
|
-
def pingroups(self):
|
|
320
|
+
def pingroups(self) -> List[Any]:
|
|
325
321
|
"""All Layout Pin groups.
|
|
326
322
|
|
|
327
323
|
. deprecated:: pyedb 0.28.0
|
|
@@ -344,18 +340,19 @@ class Padstacks(object):
|
|
|
344
340
|
return self._layout.pin_groups
|
|
345
341
|
|
|
346
342
|
@property
|
|
347
|
-
def pad_type(self):
|
|
343
|
+
def pad_type(self) -> GrpcPadType:
|
|
348
344
|
"""Return a PadType Enumerator."""
|
|
345
|
+
return GrpcPadType
|
|
349
346
|
|
|
350
347
|
def create_circular_padstack(
|
|
351
348
|
self,
|
|
352
|
-
padstackname=None,
|
|
353
|
-
holediam="300um",
|
|
354
|
-
paddiam="400um",
|
|
355
|
-
antipaddiam="600um",
|
|
356
|
-
startlayer=None,
|
|
357
|
-
endlayer=None,
|
|
358
|
-
):
|
|
349
|
+
padstackname: Optional[str] = None,
|
|
350
|
+
holediam: str = "300um",
|
|
351
|
+
paddiam: str = "400um",
|
|
352
|
+
antipaddiam: str = "600um",
|
|
353
|
+
startlayer: Optional[str] = None,
|
|
354
|
+
endlayer: Optional[str] = None,
|
|
355
|
+
) -> str:
|
|
359
356
|
"""Create a circular padstack.
|
|
360
357
|
|
|
361
358
|
Parameters
|
|
@@ -393,11 +390,11 @@ class Padstacks(object):
|
|
|
393
390
|
padstack_def = PadstackDef.create(self._pedb.db, padstackname)
|
|
394
391
|
|
|
395
392
|
padstack_data = GrpcPadstackDefData.create()
|
|
396
|
-
list_values = [
|
|
393
|
+
list_values = [Value(holediam), Value(paddiam), Value(antipaddiam)]
|
|
397
394
|
padstack_data.set_hole_parameters(
|
|
398
|
-
offset_x=
|
|
399
|
-
offset_y=
|
|
400
|
-
rotation=
|
|
395
|
+
offset_x=Value(0),
|
|
396
|
+
offset_y=Value(0),
|
|
397
|
+
rotation=Value(0),
|
|
401
398
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
402
399
|
sizes=list_values,
|
|
403
400
|
)
|
|
@@ -415,20 +412,20 @@ class Padstacks(object):
|
|
|
415
412
|
layer="Default",
|
|
416
413
|
pad_type=GrpcPadType.REGULAR_PAD,
|
|
417
414
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
418
|
-
offset_x=
|
|
419
|
-
offset_y=
|
|
420
|
-
rotation=
|
|
421
|
-
sizes=[
|
|
415
|
+
offset_x=Value(0),
|
|
416
|
+
offset_y=Value(0),
|
|
417
|
+
rotation=Value(0),
|
|
418
|
+
sizes=[Value(paddiam)],
|
|
422
419
|
)
|
|
423
420
|
|
|
424
421
|
padstack_data.set_pad_parameters(
|
|
425
422
|
layer="Default",
|
|
426
423
|
pad_type=GrpcPadType.ANTI_PAD,
|
|
427
424
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
428
|
-
offset_x=
|
|
429
|
-
offset_y=
|
|
430
|
-
rotation=
|
|
431
|
-
sizes=[
|
|
425
|
+
offset_x=Value(0),
|
|
426
|
+
offset_y=Value(0),
|
|
427
|
+
rotation=Value(0),
|
|
428
|
+
sizes=[Value(antipaddiam)],
|
|
432
429
|
)
|
|
433
430
|
|
|
434
431
|
for layer in layers:
|
|
@@ -441,25 +438,25 @@ class Padstacks(object):
|
|
|
441
438
|
layer=layer,
|
|
442
439
|
pad_type=GrpcPadType.ANTI_PAD,
|
|
443
440
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
444
|
-
offset_x=
|
|
445
|
-
offset_y=
|
|
446
|
-
rotation=
|
|
447
|
-
sizes=[
|
|
441
|
+
offset_x=Value(0),
|
|
442
|
+
offset_y=Value(0),
|
|
443
|
+
rotation=Value(0),
|
|
444
|
+
sizes=[Value(antipaddiam)],
|
|
448
445
|
)
|
|
449
446
|
|
|
450
447
|
padstack_data.set_pad_parameters(
|
|
451
448
|
layer=layer,
|
|
452
449
|
pad_type=GrpcPadType.ANTI_PAD,
|
|
453
450
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
454
|
-
offset_x=
|
|
455
|
-
offset_y=
|
|
456
|
-
rotation=
|
|
457
|
-
sizes=[
|
|
451
|
+
offset_x=Value(0),
|
|
452
|
+
offset_y=Value(0),
|
|
453
|
+
rotation=Value(0),
|
|
454
|
+
sizes=[Value(antipaddiam)],
|
|
458
455
|
)
|
|
459
456
|
|
|
460
457
|
padstack_def.data = padstack_data
|
|
461
458
|
|
|
462
|
-
def delete_padstack_instances(self, net_names
|
|
459
|
+
def delete_padstack_instances(self, net_names: Union[str, List[str]]) -> bool:
|
|
463
460
|
"""Delete padstack instances by net names.
|
|
464
461
|
|
|
465
462
|
Parameters
|
|
@@ -487,28 +484,23 @@ class Padstacks(object):
|
|
|
487
484
|
return True
|
|
488
485
|
|
|
489
486
|
def set_solderball(self, padstackInst, sballLayer_name, isTopPlaced=True, ballDiam=100e-6):
|
|
490
|
-
"""Set solderball for
|
|
487
|
+
"""Set solderball for the given PadstackInstance.
|
|
491
488
|
|
|
492
489
|
Parameters
|
|
493
490
|
----------
|
|
494
|
-
padstackInst :
|
|
495
|
-
Padstack instance
|
|
496
|
-
sballLayer_name : str
|
|
497
|
-
Name of the layer where the solder ball is placed.
|
|
498
|
-
isTopPlaced : bool, optional
|
|
499
|
-
|
|
500
|
-
ballDiam :
|
|
501
|
-
Solder ball diameter
|
|
491
|
+
padstackInst : Edb.Cell.Primitive.PadstackInstance or int
|
|
492
|
+
Padstack instance id or object.
|
|
493
|
+
sballLayer_name : str,
|
|
494
|
+
Name of the layer where the solder ball is placed. No default values.
|
|
495
|
+
isTopPlaced : bool, optional.
|
|
496
|
+
Bollean triggering is the solder ball is placed on Top or Bottom of the layer stackup.
|
|
497
|
+
ballDiam : double, optional,
|
|
498
|
+
Solder ball diameter value.
|
|
502
499
|
|
|
503
500
|
Returns
|
|
504
501
|
-------
|
|
505
502
|
bool
|
|
506
|
-
``True`` when successful, ``False`` when failed.
|
|
507
503
|
|
|
508
|
-
Examples
|
|
509
|
-
--------
|
|
510
|
-
>>> via_id = 123
|
|
511
|
-
>>> success = edb_padstacks.set_solderball(via_id, "SolderBall_Top", True, 150e-6)
|
|
512
504
|
"""
|
|
513
505
|
if isinstance(padstackInst, int):
|
|
514
506
|
psdef = self.definitions[self.instances[padstackInst].padstack_definition].edb_padstack
|
|
@@ -518,7 +510,7 @@ class Padstacks(object):
|
|
|
518
510
|
psdef = padstackInst.padstack_def
|
|
519
511
|
newdefdata = GrpcPadstackDefData.create(psdef.data)
|
|
520
512
|
newdefdata.solder_ball_shape = GrpcSolderballShape.SOLDERBALL_CYLINDER
|
|
521
|
-
newdefdata.solder_ball_param(
|
|
513
|
+
newdefdata.solder_ball_param(Value(ballDiam), Value(ballDiam))
|
|
522
514
|
sball_placement = (
|
|
523
515
|
GrpcSolderballPlacement.ABOVE_PADSTACK if isTopPlaced else GrpcSolderballPlacement.BELOW_PADSTACK
|
|
524
516
|
)
|
|
@@ -568,7 +560,9 @@ class Padstacks(object):
|
|
|
568
560
|
self, padstackinstance, use_dot_separator=use_dot_separator, name=name
|
|
569
561
|
)
|
|
570
562
|
|
|
571
|
-
def get_pin_from_component_and_net(
|
|
563
|
+
def get_pin_from_component_and_net(
|
|
564
|
+
self, refdes: Optional[str] = None, netname: Optional[str] = None
|
|
565
|
+
) -> (List)[PadstackInstance]:
|
|
572
566
|
"""Retrieve pins by component reference designator and net name.
|
|
573
567
|
|
|
574
568
|
Parameters
|
|
@@ -637,7 +631,9 @@ class Padstacks(object):
|
|
|
637
631
|
)
|
|
638
632
|
return self.get_pin_from_component_and_net(refdes=refdes, netname=netname)
|
|
639
633
|
|
|
640
|
-
def get_pad_parameters(
|
|
634
|
+
def get_pad_parameters(
|
|
635
|
+
self, pin: PadstackInstance, layername: str, pad_type: str = "regular_pad"
|
|
636
|
+
) -> Tuple[GrpcPadGeometryType, List[float], List[float], float]:
|
|
641
637
|
"""Get pad parameters for a pin on a specific layer.
|
|
642
638
|
|
|
643
639
|
Parameters
|
|
@@ -675,10 +671,10 @@ class Padstacks(object):
|
|
|
675
671
|
padparams = pin.padstack_def.data.get_pad_parameters(layername, pad_type)
|
|
676
672
|
if len(padparams) == 5: # non polygon via
|
|
677
673
|
geometry_type = padparams[0]
|
|
678
|
-
parameters = [i
|
|
679
|
-
offset_x = padparams[2]
|
|
680
|
-
offset_y = padparams[3]
|
|
681
|
-
rotation = padparams[4]
|
|
674
|
+
parameters = [Value(i) for i in padparams[1]]
|
|
675
|
+
offset_x = Value(padparams[2])
|
|
676
|
+
offset_y = Value(padparams[3])
|
|
677
|
+
rotation = Value(padparams[4])
|
|
682
678
|
return geometry_type.name, parameters, offset_x, offset_y, rotation
|
|
683
679
|
elif len(padparams) == 4: # polygon based
|
|
684
680
|
from ansys.edb.core.geometry.polygon_data import (
|
|
@@ -686,15 +682,15 @@ class Padstacks(object):
|
|
|
686
682
|
)
|
|
687
683
|
|
|
688
684
|
if isinstance(padparams[0], GrpcPolygonData):
|
|
689
|
-
points = [[pt.x
|
|
690
|
-
offset_x = padparams[1]
|
|
691
|
-
offset_y = padparams[2]
|
|
692
|
-
rotation = padparams[3]
|
|
685
|
+
points = [[Value(pt.x), Value(pt.y)] for pt in padparams[0].points]
|
|
686
|
+
offset_x = Value(padparams[1])
|
|
687
|
+
offset_y = Value(padparams[2])
|
|
688
|
+
rotation = Value(padparams[3])
|
|
693
689
|
geometry_type = GrpcPadGeometryType.PADGEOMTYPE_POLYGON
|
|
694
690
|
return geometry_type.name, points, offset_x, offset_y, rotation
|
|
695
691
|
return 0, [0], 0, 0, 0
|
|
696
692
|
|
|
697
|
-
def set_all_antipad_value(self, value):
|
|
693
|
+
def set_all_antipad_value(self, value: Union[float, str]) -> bool:
|
|
698
694
|
"""Set anti-pad value for all padstack definitions.
|
|
699
695
|
|
|
700
696
|
Parameters
|
|
@@ -725,11 +721,11 @@ class Padstacks(object):
|
|
|
725
721
|
cloned_padstack_data.set_pad_parameters(
|
|
726
722
|
layer=layer,
|
|
727
723
|
pad_type=GrpcPadType.ANTI_PAD,
|
|
728
|
-
offset_x=
|
|
729
|
-
offset_y=
|
|
730
|
-
rotation=
|
|
724
|
+
offset_x=Value(offset_x),
|
|
725
|
+
offset_y=Value(offset_y),
|
|
726
|
+
rotation=Value(rotation),
|
|
731
727
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
732
|
-
sizes=[
|
|
728
|
+
sizes=[Value(value)],
|
|
733
729
|
)
|
|
734
730
|
self._logger.info(
|
|
735
731
|
"Pad-stack definition {}, anti-pad on layer {}, has been set to {}".format(
|
|
@@ -749,7 +745,9 @@ class Padstacks(object):
|
|
|
749
745
|
padstack.data = cloned_padstack_data
|
|
750
746
|
return all_succeed
|
|
751
747
|
|
|
752
|
-
def check_and_fix_via_plating(
|
|
748
|
+
def check_and_fix_via_plating(
|
|
749
|
+
self, minimum_value_to_replace: float = 0.0, default_plating_ratio: float = 0.2
|
|
750
|
+
) -> bool:
|
|
753
751
|
"""Check and fix via plating ratios below a minimum value.
|
|
754
752
|
|
|
755
753
|
Parameters
|
|
@@ -776,7 +774,7 @@ class Padstacks(object):
|
|
|
776
774
|
)
|
|
777
775
|
return True
|
|
778
776
|
|
|
779
|
-
def get_via_instance_from_net(self, net_list=None):
|
|
777
|
+
def get_via_instance_from_net(self, net_list: Optional[Union[str, List[str]]] = None) -> List[PadstackInstance]:
|
|
780
778
|
"""Get via instances by net names.
|
|
781
779
|
|
|
782
780
|
Parameters
|
|
@@ -797,7 +795,7 @@ class Padstacks(object):
|
|
|
797
795
|
if net_list and not isinstance(net_list, list):
|
|
798
796
|
net_list = [net_list]
|
|
799
797
|
via_list = []
|
|
800
|
-
for inst in self._layout.padstack_instances:
|
|
798
|
+
for inst_id, inst in self._layout.padstack_instances.items():
|
|
801
799
|
pad_layers_name = inst.padstack_def.data.layer_names
|
|
802
800
|
if len(pad_layers_name) > 1:
|
|
803
801
|
if not net_list:
|
|
@@ -809,31 +807,31 @@ class Padstacks(object):
|
|
|
809
807
|
|
|
810
808
|
def create(
|
|
811
809
|
self,
|
|
812
|
-
padstackname=None,
|
|
813
|
-
holediam="300um",
|
|
814
|
-
paddiam="400um",
|
|
815
|
-
antipaddiam="600um",
|
|
816
|
-
pad_shape="Circle",
|
|
817
|
-
antipad_shape="Circle",
|
|
818
|
-
x_size="600um",
|
|
819
|
-
y_size="600um",
|
|
820
|
-
corner_radius="300um",
|
|
821
|
-
offset_x="0.0",
|
|
822
|
-
offset_y="0.0",
|
|
823
|
-
rotation="0.0",
|
|
824
|
-
has_hole=True,
|
|
825
|
-
pad_offset_x="0.0",
|
|
826
|
-
pad_offset_y="0.0",
|
|
827
|
-
pad_rotation="0.0",
|
|
828
|
-
pad_polygon=None,
|
|
829
|
-
antipad_polygon=None,
|
|
830
|
-
polygon_hole=None,
|
|
831
|
-
start_layer=None,
|
|
832
|
-
stop_layer=None,
|
|
833
|
-
add_default_layer=False,
|
|
834
|
-
anti_pad_x_size="600um",
|
|
835
|
-
anti_pad_y_size="600um",
|
|
836
|
-
hole_range="upper_pad_to_lower_pad",
|
|
810
|
+
padstackname: Optional[str] = None,
|
|
811
|
+
holediam: str = "300um",
|
|
812
|
+
paddiam: str = "400um",
|
|
813
|
+
antipaddiam: str = "600um",
|
|
814
|
+
pad_shape: str = "Circle",
|
|
815
|
+
antipad_shape: str = "Circle",
|
|
816
|
+
x_size: str = "600um",
|
|
817
|
+
y_size: str = "600um",
|
|
818
|
+
corner_radius: str = "300um",
|
|
819
|
+
offset_x: str = "0.0",
|
|
820
|
+
offset_y: str = "0.0",
|
|
821
|
+
rotation: str = "0.0",
|
|
822
|
+
has_hole: bool = True,
|
|
823
|
+
pad_offset_x: str = "0.0",
|
|
824
|
+
pad_offset_y: str = "0.0",
|
|
825
|
+
pad_rotation: str = "0.0",
|
|
826
|
+
pad_polygon: Optional[Any] = None,
|
|
827
|
+
antipad_polygon: Optional[Any] = None,
|
|
828
|
+
polygon_hole: Optional[Any] = None,
|
|
829
|
+
start_layer: Optional[str] = None,
|
|
830
|
+
stop_layer: Optional[str] = None,
|
|
831
|
+
add_default_layer: bool = False,
|
|
832
|
+
anti_pad_x_size: str = "600um",
|
|
833
|
+
anti_pad_y_size: str = "600um",
|
|
834
|
+
hole_range: str = "upper_pad_to_lower_pad",
|
|
837
835
|
):
|
|
838
836
|
"""Create a padstack definition.
|
|
839
837
|
|
|
@@ -896,11 +894,11 @@ class Padstacks(object):
|
|
|
896
894
|
str
|
|
897
895
|
Name of the created padstack definition.
|
|
898
896
|
"""
|
|
899
|
-
holediam =
|
|
900
|
-
paddiam =
|
|
901
|
-
antipaddiam =
|
|
897
|
+
holediam = Value(holediam)
|
|
898
|
+
paddiam = Value(paddiam)
|
|
899
|
+
antipaddiam = Value(antipaddiam)
|
|
902
900
|
layers = list(self._pedb.stackup.signal_layers.keys())[:]
|
|
903
|
-
value0 =
|
|
901
|
+
value0 = Value("0.0")
|
|
904
902
|
if not padstackname:
|
|
905
903
|
padstackname = generate_unique_name("VIA")
|
|
906
904
|
padstack_data = GrpcPadstackDefData.create()
|
|
@@ -913,7 +911,7 @@ class Padstacks(object):
|
|
|
913
911
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_CIRCLE,
|
|
914
912
|
sizes=hole_param,
|
|
915
913
|
)
|
|
916
|
-
padstack_data.plating_percentage =
|
|
914
|
+
padstack_data.plating_percentage = Value(20.0)
|
|
917
915
|
elif polygon_hole:
|
|
918
916
|
if isinstance(polygon_hole, list):
|
|
919
917
|
polygon_hole = GrpcPolygonData(points=polygon_hole)
|
|
@@ -924,18 +922,18 @@ class Padstacks(object):
|
|
|
924
922
|
type_geom=GrpcPadGeometryType.PADGEOMTYPE_POLYGON,
|
|
925
923
|
fp=polygon_hole,
|
|
926
924
|
)
|
|
927
|
-
padstack_data.plating_percentage =
|
|
925
|
+
padstack_data.plating_percentage = Value(20.0)
|
|
928
926
|
else:
|
|
929
927
|
pass
|
|
930
928
|
|
|
931
|
-
x_size =
|
|
932
|
-
y_size =
|
|
933
|
-
corner_radius =
|
|
934
|
-
pad_offset_x =
|
|
935
|
-
pad_offset_y =
|
|
936
|
-
pad_rotation =
|
|
937
|
-
anti_pad_x_size =
|
|
938
|
-
anti_pad_y_size =
|
|
929
|
+
x_size = Value(x_size)
|
|
930
|
+
y_size = Value(y_size)
|
|
931
|
+
corner_radius = Value(corner_radius)
|
|
932
|
+
pad_offset_x = Value(pad_offset_x)
|
|
933
|
+
pad_offset_y = Value(pad_offset_y)
|
|
934
|
+
pad_rotation = Value(pad_rotation)
|
|
935
|
+
anti_pad_x_size = Value(anti_pad_x_size)
|
|
936
|
+
anti_pad_y_size = Value(anti_pad_y_size)
|
|
939
937
|
|
|
940
938
|
if hole_range == "through": # pragma no cover
|
|
941
939
|
padstack_data.hole_range = GrpcPadstackHoleRange.THROUGH
|
|
@@ -1031,14 +1029,14 @@ class Padstacks(object):
|
|
|
1031
1029
|
self._logger.info(f"Padstack {padstackname} create correctly")
|
|
1032
1030
|
return padstackname
|
|
1033
1031
|
|
|
1034
|
-
def _get_pin_layer_range(self, pin):
|
|
1032
|
+
def _get_pin_layer_range(self, pin: PadstackInstance) -> Union[Tuple[str, str], bool]:
|
|
1035
1033
|
layers = pin.get_layer_range()
|
|
1036
1034
|
if layers:
|
|
1037
1035
|
return layers[0], layers[1]
|
|
1038
1036
|
else:
|
|
1039
1037
|
return False
|
|
1040
1038
|
|
|
1041
|
-
def duplicate(self, target_padstack_name, new_padstack_name=""):
|
|
1039
|
+
def duplicate(self, target_padstack_name: str, new_padstack_name: str = "") -> str:
|
|
1042
1040
|
"""Duplicate a padstack definition.
|
|
1043
1041
|
|
|
1044
1042
|
Parameters
|
|
@@ -1062,16 +1060,16 @@ class Padstacks(object):
|
|
|
1062
1060
|
|
|
1063
1061
|
def place(
|
|
1064
1062
|
self,
|
|
1065
|
-
position,
|
|
1066
|
-
definition_name,
|
|
1067
|
-
net_name="",
|
|
1068
|
-
via_name="",
|
|
1069
|
-
rotation=0.0,
|
|
1070
|
-
fromlayer=None,
|
|
1071
|
-
tolayer=None,
|
|
1072
|
-
solderlayer=None,
|
|
1073
|
-
is_pin=False,
|
|
1074
|
-
):
|
|
1063
|
+
position: List[float],
|
|
1064
|
+
definition_name: str,
|
|
1065
|
+
net_name: str = "",
|
|
1066
|
+
via_name: str = "",
|
|
1067
|
+
rotation: float = 0.0,
|
|
1068
|
+
fromlayer: Optional[str] = None,
|
|
1069
|
+
tolayer: Optional[str] = None,
|
|
1070
|
+
solderlayer: Optional[str] = None,
|
|
1071
|
+
is_pin: bool = False,
|
|
1072
|
+
) -> PadstackInstance:
|
|
1075
1073
|
"""Place a padstack instance.
|
|
1076
1074
|
|
|
1077
1075
|
Parameters
|
|
@@ -1105,10 +1103,10 @@ class Padstacks(object):
|
|
|
1105
1103
|
if pad == definition_name:
|
|
1106
1104
|
padstack_def = self.definitions[pad]
|
|
1107
1105
|
position = GrpcPointData(
|
|
1108
|
-
[
|
|
1106
|
+
[Value(position[0], self._pedb.active_cell), Value(position[1], self._pedb.active_cell)]
|
|
1109
1107
|
)
|
|
1110
1108
|
net = self._pedb.nets.find_or_create_net(net_name)
|
|
1111
|
-
rotation =
|
|
1109
|
+
rotation = Value(rotation * math.pi / 180)
|
|
1112
1110
|
sign_layers_values = {i: v for i, v in self._pedb.stackup.signal_layers.items()}
|
|
1113
1111
|
sign_layers = list(sign_layers_values.keys())
|
|
1114
1112
|
if not fromlayer:
|
|
@@ -1147,9 +1145,9 @@ class Padstacks(object):
|
|
|
1147
1145
|
padstack_instance.is_layout_pin = is_pin
|
|
1148
1146
|
return PadstackInstance(self._pedb, padstack_instance)
|
|
1149
1147
|
else:
|
|
1150
|
-
|
|
1148
|
+
raise RuntimeError("Place padstack failed")
|
|
1151
1149
|
|
|
1152
|
-
def remove_pads_from_padstack(self, padstack_name, layer_name=None):
|
|
1150
|
+
def remove_pads_from_padstack(self, padstack_name: str, layer_name: Optional[str] = None):
|
|
1153
1151
|
"""Remove pads from a padstack definition on specified layers.
|
|
1154
1152
|
|
|
1155
1153
|
Parameters
|
|
@@ -1166,8 +1164,8 @@ class Padstacks(object):
|
|
|
1166
1164
|
"""
|
|
1167
1165
|
pad_type = GrpcPadType.REGULAR_PAD
|
|
1168
1166
|
pad_geo = GrpcPadGeometryType.PADGEOMTYPE_CIRCLE
|
|
1169
|
-
vals =
|
|
1170
|
-
params = [
|
|
1167
|
+
vals = Value(0)
|
|
1168
|
+
params = [Value(0)]
|
|
1171
1169
|
new_padstack_definition_data = GrpcPadstackDefData(self.definitions[padstack_name].data)
|
|
1172
1170
|
if not layer_name:
|
|
1173
1171
|
layer_name = list(self._pedb.stackup.signal_layers.keys())
|
|
@@ -1188,18 +1186,18 @@ class Padstacks(object):
|
|
|
1188
1186
|
|
|
1189
1187
|
def set_pad_property(
|
|
1190
1188
|
self,
|
|
1191
|
-
padstack_name,
|
|
1192
|
-
layer_name=None,
|
|
1193
|
-
pad_shape="Circle",
|
|
1194
|
-
pad_params=0,
|
|
1195
|
-
pad_x_offset=0,
|
|
1196
|
-
pad_y_offset=0,
|
|
1197
|
-
pad_rotation=0,
|
|
1198
|
-
antipad_shape="Circle",
|
|
1199
|
-
antipad_params=0,
|
|
1200
|
-
antipad_x_offset=0,
|
|
1201
|
-
antipad_y_offset=0,
|
|
1202
|
-
antipad_rotation=0,
|
|
1189
|
+
padstack_name: str,
|
|
1190
|
+
layer_name: Optional[str] = None,
|
|
1191
|
+
pad_shape: str = "Circle",
|
|
1192
|
+
pad_params: Union[float, List[float]] = 0,
|
|
1193
|
+
pad_x_offset: float = 0,
|
|
1194
|
+
pad_y_offset: float = 0,
|
|
1195
|
+
pad_rotation: float = 0,
|
|
1196
|
+
antipad_shape: str = "Circle",
|
|
1197
|
+
antipad_params: Union[float, List[float]] = 0,
|
|
1198
|
+
antipad_x_offset: float = 0,
|
|
1199
|
+
antipad_y_offset: float = 0,
|
|
1200
|
+
antipad_rotation: float = 0,
|
|
1203
1201
|
):
|
|
1204
1202
|
"""Set pad and anti-pad properties for a padstack definition.
|
|
1205
1203
|
|
|
@@ -1245,18 +1243,18 @@ class Padstacks(object):
|
|
|
1245
1243
|
pad_shape = shape_dict[pad_shape]
|
|
1246
1244
|
if not isinstance(pad_params, list):
|
|
1247
1245
|
pad_params = [pad_params]
|
|
1248
|
-
pad_params = [
|
|
1249
|
-
pad_x_offset =
|
|
1250
|
-
pad_y_offset =
|
|
1251
|
-
pad_rotation =
|
|
1246
|
+
pad_params = [Value(i) for i in pad_params]
|
|
1247
|
+
pad_x_offset = Value(pad_x_offset)
|
|
1248
|
+
pad_y_offset = Value(pad_y_offset)
|
|
1249
|
+
pad_rotation = Value(pad_rotation)
|
|
1252
1250
|
|
|
1253
1251
|
antipad_shape = shape_dict[antipad_shape]
|
|
1254
1252
|
if not isinstance(antipad_params, list):
|
|
1255
1253
|
antipad_params = [antipad_params]
|
|
1256
|
-
antipad_params = [
|
|
1257
|
-
antipad_x_offset =
|
|
1258
|
-
antipad_y_offset =
|
|
1259
|
-
antipad_rotation =
|
|
1254
|
+
antipad_params = [Value(i) for i in antipad_params]
|
|
1255
|
+
antipad_x_offset = Value(antipad_x_offset)
|
|
1256
|
+
antipad_y_offset = Value(antipad_y_offset)
|
|
1257
|
+
antipad_rotation = Value(antipad_rotation)
|
|
1260
1258
|
new_padstack_def = GrpcPadstackDefData(self.definitions[padstack_name].data.msg)
|
|
1261
1259
|
if not layer_name:
|
|
1262
1260
|
layer_name = list(self._pedb.stackup.signal_layers.keys())
|
|
@@ -1284,15 +1282,38 @@ class Padstacks(object):
|
|
|
1284
1282
|
self.definitions[padstack_name].data = new_padstack_def
|
|
1285
1283
|
return True
|
|
1286
1284
|
|
|
1285
|
+
def get_padstack_instance_by_net_name(self, net: str):
|
|
1286
|
+
"""Get padstack instances by net name.
|
|
1287
|
+
|
|
1288
|
+
.. deprecated:: 0.55.0
|
|
1289
|
+
Use: :func:`get_instances` with `net_name` parameter instead.
|
|
1290
|
+
|
|
1291
|
+
Parameters
|
|
1292
|
+
----------
|
|
1293
|
+
net : str
|
|
1294
|
+
Net name to filter padstack instances.
|
|
1295
|
+
|
|
1296
|
+
Returns
|
|
1297
|
+
-------
|
|
1298
|
+
list[:class:`pyedb.grpc.database.primitive.padstack_instance.PadstackInstance`]
|
|
1299
|
+
List of padstack instances associated with the specified net.
|
|
1300
|
+
"""
|
|
1301
|
+
warnings.warn(
|
|
1302
|
+
"`get_padstack_instance_by_net_name` is deprecated, use `get_instances` with `net_name` "
|
|
1303
|
+
"parameter instead.",
|
|
1304
|
+
DeprecationWarning,
|
|
1305
|
+
)
|
|
1306
|
+
return self.get_instances(net_name=net)
|
|
1307
|
+
|
|
1287
1308
|
def get_instances(
|
|
1288
1309
|
self,
|
|
1289
|
-
name=None,
|
|
1290
|
-
pid=None,
|
|
1291
|
-
definition_name=None,
|
|
1292
|
-
net_name=None,
|
|
1293
|
-
component_reference_designator=None,
|
|
1294
|
-
component_pin=None,
|
|
1295
|
-
):
|
|
1310
|
+
name: Optional[str] = None,
|
|
1311
|
+
pid: Optional[int] = None,
|
|
1312
|
+
definition_name: Optional[str] = None,
|
|
1313
|
+
net_name: Optional[str] = None,
|
|
1314
|
+
component_reference_designator: Optional[str] = None,
|
|
1315
|
+
component_pin: Optional[str] = None,
|
|
1316
|
+
) -> List[PadstackInstance]:
|
|
1296
1317
|
"""Get padstack instances by search criteria.
|
|
1297
1318
|
|
|
1298
1319
|
Parameters
|
|
@@ -1319,7 +1340,7 @@ class Padstacks(object):
|
|
|
1319
1340
|
if pid:
|
|
1320
1341
|
return instances_by_id[pid]
|
|
1321
1342
|
elif name:
|
|
1322
|
-
instances = [inst for inst in list(self.instances.values()) if inst.
|
|
1343
|
+
instances = [inst for inst in list(self.instances.values()) if inst.aedt_name == name]
|
|
1323
1344
|
if instances:
|
|
1324
1345
|
return instances
|
|
1325
1346
|
else:
|
|
@@ -1344,8 +1365,13 @@ class Padstacks(object):
|
|
|
1344
1365
|
return instances
|
|
1345
1366
|
|
|
1346
1367
|
def get_reference_pins(
|
|
1347
|
-
self,
|
|
1348
|
-
|
|
1368
|
+
self,
|
|
1369
|
+
positive_pin: Union[int, str, PadstackInstance],
|
|
1370
|
+
reference_net: str = "gnd",
|
|
1371
|
+
search_radius: float = 5e-3,
|
|
1372
|
+
max_limit: int = 0,
|
|
1373
|
+
component_only: bool = True,
|
|
1374
|
+
) -> List[PadstackInstance]:
|
|
1349
1375
|
"""Find reference pins near a specified pin.
|
|
1350
1376
|
|
|
1351
1377
|
Parameters
|
|
@@ -1390,7 +1416,7 @@ class Padstacks(object):
|
|
|
1390
1416
|
pinlist = [pin[1] for pin in sorted(pin_dict.items())[:max_limit]]
|
|
1391
1417
|
return pinlist
|
|
1392
1418
|
|
|
1393
|
-
def get_padstack_instances_rtree_index(self, nets=None):
|
|
1419
|
+
def get_padstack_instances_rtree_index(self, nets: Optional[Union[str, List[str]]] = None) -> rtree.index.Index:
|
|
1394
1420
|
"""Returns padstack instances Rtree index.
|
|
1395
1421
|
|
|
1396
1422
|
Parameters
|
|
@@ -1415,7 +1441,12 @@ class Padstacks(object):
|
|
|
1415
1441
|
padstack_instances_index.insert(inst.edb_uid, inst.position)
|
|
1416
1442
|
return padstack_instances_index
|
|
1417
1443
|
|
|
1418
|
-
def get_padstack_instances_id_intersecting_polygon(
|
|
1444
|
+
def get_padstack_instances_id_intersecting_polygon(
|
|
1445
|
+
self,
|
|
1446
|
+
points: List[Tuple[float, float]],
|
|
1447
|
+
nets: Optional[Union[str, List[str]]] = None,
|
|
1448
|
+
padstack_instances_index: Optional[Dict[int, Tuple[float, float]]] = None,
|
|
1449
|
+
) -> List[int]:
|
|
1419
1450
|
"""Returns the list of padstack instances ID intersecting a given bounding box and nets.
|
|
1420
1451
|
|
|
1421
1452
|
Parameters
|
|
@@ -1446,7 +1477,12 @@ class Padstacks(object):
|
|
|
1446
1477
|
ind for ind, pt in padstack_instances_index.items() if GeometryOperators.is_point_in_polygon(pt, points)
|
|
1447
1478
|
]
|
|
1448
1479
|
|
|
1449
|
-
def get_padstack_instances_intersecting_bounding_box(
|
|
1480
|
+
def get_padstack_instances_intersecting_bounding_box(
|
|
1481
|
+
self,
|
|
1482
|
+
bounding_box: List[float],
|
|
1483
|
+
nets: Optional[Union[str, List[str]]] = None,
|
|
1484
|
+
padstack_instances_index: Optional[rtree.index.Index] = None,
|
|
1485
|
+
) -> List[PadstackInstance]:
|
|
1450
1486
|
"""Returns the list of padstack instances ID intersecting a given bounding box and nets.
|
|
1451
1487
|
Parameters
|
|
1452
1488
|
----------
|
|
@@ -1475,12 +1511,12 @@ class Padstacks(object):
|
|
|
1475
1511
|
|
|
1476
1512
|
def merge_via_along_lines(
|
|
1477
1513
|
self,
|
|
1478
|
-
net_name="GND",
|
|
1479
|
-
distance_threshold=5e-3,
|
|
1480
|
-
minimum_via_number=6,
|
|
1481
|
-
selected_angles=None,
|
|
1482
|
-
padstack_instances_id=None,
|
|
1483
|
-
):
|
|
1514
|
+
net_name: str = "GND",
|
|
1515
|
+
distance_threshold: float = 5e-3,
|
|
1516
|
+
minimum_via_number: int = 6,
|
|
1517
|
+
selected_angles: Optional[List[float]] = None,
|
|
1518
|
+
padstack_instances_id: Optional[List[int]] = None,
|
|
1519
|
+
) -> None:
|
|
1484
1520
|
"""Replace padstack instances along lines into a single polygon.
|
|
1485
1521
|
|
|
1486
1522
|
Detect all pad-stack instances that are placed along lines and replace them by a single polygon based one
|
|
@@ -1622,7 +1658,13 @@ class Padstacks(object):
|
|
|
1622
1658
|
|
|
1623
1659
|
return True
|
|
1624
1660
|
|
|
1625
|
-
def merge_via(
|
|
1661
|
+
def merge_via(
|
|
1662
|
+
self,
|
|
1663
|
+
contour_boxes: List[List[float]],
|
|
1664
|
+
net_filter: Optional[Union[str, List[str]]] = None,
|
|
1665
|
+
start_layer: Optional[str] = None,
|
|
1666
|
+
stop_layer: Optional[str] = None,
|
|
1667
|
+
) -> bool:
|
|
1626
1668
|
"""Evaluate pad-stack instances included on the provided point list and replace all by single instance.
|
|
1627
1669
|
|
|
1628
1670
|
Parameters
|
|
@@ -1688,7 +1730,9 @@ class Padstacks(object):
|
|
|
1688
1730
|
[self.instances[inst].delete() for inst in instances]
|
|
1689
1731
|
return merged_via_ids
|
|
1690
1732
|
|
|
1691
|
-
def reduce_via_in_bounding_box(
|
|
1733
|
+
def reduce_via_in_bounding_box(
|
|
1734
|
+
self, bounding_box: List[float], x_samples: int, y_samples: int, nets: Optional[Union[str, List[str]]] = None
|
|
1735
|
+
) -> bool:
|
|
1692
1736
|
"""
|
|
1693
1737
|
reduce the number of vias intersecting bounding box and nets by x and y samples.
|
|
1694
1738
|
|
|
@@ -1740,3 +1784,72 @@ class Padstacks(object):
|
|
|
1740
1784
|
if item not in to_keep:
|
|
1741
1785
|
all_instances[item].delete()
|
|
1742
1786
|
return True
|
|
1787
|
+
|
|
1788
|
+
@staticmethod
|
|
1789
|
+
def dbscan(
|
|
1790
|
+
padstack: Dict[int, List[float]], max_distance: float = 1e-3, min_samples: int = 5
|
|
1791
|
+
) -> Dict[int, List[str]]:
|
|
1792
|
+
"""
|
|
1793
|
+
density based spatial clustering for padstack instances
|
|
1794
|
+
|
|
1795
|
+
Parameters
|
|
1796
|
+
----------
|
|
1797
|
+
padstack : dict.
|
|
1798
|
+
padstack id: [x, y]
|
|
1799
|
+
|
|
1800
|
+
max_distance: float
|
|
1801
|
+
maximum distance between two points to be included in one cluster
|
|
1802
|
+
|
|
1803
|
+
min_samples: int
|
|
1804
|
+
minimum number of points that a cluster must have
|
|
1805
|
+
|
|
1806
|
+
Returns
|
|
1807
|
+
-------
|
|
1808
|
+
dict
|
|
1809
|
+
clusters {cluster label: [padstack ids]} <
|
|
1810
|
+
"""
|
|
1811
|
+
|
|
1812
|
+
padstack_ids = list(padstack.keys())
|
|
1813
|
+
xy_array = np.array([padstack[pid] for pid in padstack_ids])
|
|
1814
|
+
n = len(padstack_ids)
|
|
1815
|
+
|
|
1816
|
+
labels = -1 * np.ones(n, dtype=int)
|
|
1817
|
+
visited = np.zeros(n, dtype=bool)
|
|
1818
|
+
cluster_id = 0
|
|
1819
|
+
|
|
1820
|
+
def region_query(point_idx):
|
|
1821
|
+
distances = np.linalg.norm(xy_array - xy_array[point_idx], axis=1)
|
|
1822
|
+
return np.where(distances <= max_distance)[0]
|
|
1823
|
+
|
|
1824
|
+
def expand_cluster(point_idx, neighbors):
|
|
1825
|
+
nonlocal cluster_id
|
|
1826
|
+
labels[point_idx] = cluster_id
|
|
1827
|
+
i = 0
|
|
1828
|
+
while i < len(neighbors):
|
|
1829
|
+
neighbor_idx = neighbors[i]
|
|
1830
|
+
if not visited[neighbor_idx]:
|
|
1831
|
+
visited[neighbor_idx] = True
|
|
1832
|
+
neighbor_neighbors = region_query(neighbor_idx)
|
|
1833
|
+
if len(neighbor_neighbors) >= min_samples:
|
|
1834
|
+
neighbors = np.concatenate((neighbors, neighbor_neighbors))
|
|
1835
|
+
if labels[neighbor_idx] == -1:
|
|
1836
|
+
labels[neighbor_idx] = cluster_id
|
|
1837
|
+
i += 1
|
|
1838
|
+
|
|
1839
|
+
for point_idx in range(n):
|
|
1840
|
+
if visited[point_idx]:
|
|
1841
|
+
continue
|
|
1842
|
+
visited[point_idx] = True
|
|
1843
|
+
neighbors = region_query(point_idx)
|
|
1844
|
+
if len(neighbors) < min_samples:
|
|
1845
|
+
labels[point_idx] = -1
|
|
1846
|
+
else:
|
|
1847
|
+
expand_cluster(point_idx, neighbors)
|
|
1848
|
+
cluster_id += 1
|
|
1849
|
+
|
|
1850
|
+
# group point IDs by label
|
|
1851
|
+
clusters = defaultdict(list)
|
|
1852
|
+
for i, label in enumerate(labels):
|
|
1853
|
+
clusters[int(label)].append(padstack_ids[i])
|
|
1854
|
+
|
|
1855
|
+
return dict(clusters)
|