pyedb 0.2.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.

Files changed (128) hide show
  1. pyedb/__init__.py +17 -0
  2. pyedb/dotnet/__init__.py +0 -0
  3. pyedb/dotnet/application/Variables.py +2261 -0
  4. pyedb/dotnet/application/__init__.py +0 -0
  5. pyedb/dotnet/clr_module.py +103 -0
  6. pyedb/dotnet/edb.py +4237 -0
  7. pyedb/dotnet/edb_core/__init__.py +1 -0
  8. pyedb/dotnet/edb_core/cell/__init__.py +0 -0
  9. pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
  10. pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
  11. pyedb/dotnet/edb_core/components.py +2669 -0
  12. pyedb/dotnet/edb_core/configuration.py +423 -0
  13. pyedb/dotnet/edb_core/definition/__init__.py +0 -0
  14. pyedb/dotnet/edb_core/definition/component_def.py +166 -0
  15. pyedb/dotnet/edb_core/definition/component_model.py +30 -0
  16. pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
  17. pyedb/dotnet/edb_core/definition/definitions.py +12 -0
  18. pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
  19. pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
  20. pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
  21. pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
  22. pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
  23. pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
  24. pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
  25. pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
  26. pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
  27. pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
  28. pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
  29. pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
  30. pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
  31. pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
  32. pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
  33. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
  34. pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
  35. pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
  36. pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
  37. pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
  38. pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
  39. pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
  40. pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
  41. pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
  42. pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
  43. pyedb/dotnet/edb_core/general.py +181 -0
  44. pyedb/dotnet/edb_core/hfss.py +1646 -0
  45. pyedb/dotnet/edb_core/layout.py +1244 -0
  46. pyedb/dotnet/edb_core/layout_validation.py +272 -0
  47. pyedb/dotnet/edb_core/materials.py +939 -0
  48. pyedb/dotnet/edb_core/net_class.py +335 -0
  49. pyedb/dotnet/edb_core/nets.py +1215 -0
  50. pyedb/dotnet/edb_core/padstack.py +1389 -0
  51. pyedb/dotnet/edb_core/siwave.py +1427 -0
  52. pyedb/dotnet/edb_core/stackup.py +2703 -0
  53. pyedb/edb_logger.py +396 -0
  54. pyedb/generic/__init__.py +0 -0
  55. pyedb/generic/constants.py +1063 -0
  56. pyedb/generic/data_handlers.py +320 -0
  57. pyedb/generic/design_types.py +104 -0
  58. pyedb/generic/filesystem.py +150 -0
  59. pyedb/generic/general_methods.py +1535 -0
  60. pyedb/generic/plot.py +1840 -0
  61. pyedb/generic/process.py +285 -0
  62. pyedb/generic/settings.py +224 -0
  63. pyedb/ipc2581/__init__.py +0 -0
  64. pyedb/ipc2581/bom/__init__.py +0 -0
  65. pyedb/ipc2581/bom/bom.py +21 -0
  66. pyedb/ipc2581/bom/bom_item.py +32 -0
  67. pyedb/ipc2581/bom/characteristics.py +37 -0
  68. pyedb/ipc2581/bom/refdes.py +16 -0
  69. pyedb/ipc2581/content/__init__.py +0 -0
  70. pyedb/ipc2581/content/color.py +38 -0
  71. pyedb/ipc2581/content/content.py +55 -0
  72. pyedb/ipc2581/content/dictionary_color.py +29 -0
  73. pyedb/ipc2581/content/dictionary_fill.py +28 -0
  74. pyedb/ipc2581/content/dictionary_line.py +30 -0
  75. pyedb/ipc2581/content/entry_color.py +13 -0
  76. pyedb/ipc2581/content/entry_line.py +14 -0
  77. pyedb/ipc2581/content/fill.py +15 -0
  78. pyedb/ipc2581/content/layer_ref.py +10 -0
  79. pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
  80. pyedb/ipc2581/ecad/__init__.py +0 -0
  81. pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
  82. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
  83. pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
  84. pyedb/ipc2581/ecad/cad_data/component.py +41 -0
  85. pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
  86. pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
  87. pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
  88. pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
  89. pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
  90. pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
  91. pyedb/ipc2581/ecad/cad_data/package.py +104 -0
  92. pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
  93. pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
  94. pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
  95. pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
  96. pyedb/ipc2581/ecad/cad_data/path.py +89 -0
  97. pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
  98. pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
  99. pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
  100. pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
  101. pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
  102. pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
  103. pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
  104. pyedb/ipc2581/ecad/cad_data/step.py +275 -0
  105. pyedb/ipc2581/ecad/cad_header.py +33 -0
  106. pyedb/ipc2581/ecad/ecad.py +19 -0
  107. pyedb/ipc2581/ecad/spec.py +46 -0
  108. pyedb/ipc2581/history_record.py +37 -0
  109. pyedb/ipc2581/ipc2581.py +387 -0
  110. pyedb/ipc2581/logistic_header.py +25 -0
  111. pyedb/misc/__init__.py +0 -0
  112. pyedb/misc/aedtlib_personalib_install.py +14 -0
  113. pyedb/misc/downloads.py +322 -0
  114. pyedb/misc/misc.py +67 -0
  115. pyedb/misc/pyedb.runtimeconfig.json +13 -0
  116. pyedb/misc/siw_feature_config/__init__.py +0 -0
  117. pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
  118. pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
  119. pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
  120. pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
  121. pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
  122. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
  123. pyedb/misc/utilities.py +27 -0
  124. pyedb/modeler/geometry_operators.py +2082 -0
  125. pyedb-0.2.0.dist-info/LICENSE +21 -0
  126. pyedb-0.2.0.dist-info/METADATA +208 -0
  127. pyedb-0.2.0.dist-info/RECORD +128 -0
  128. pyedb-0.2.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,1389 @@
1
+ """
2
+ This module contains the `EdbPadstacks` class.
3
+ """
4
+ import math
5
+ import warnings
6
+
7
+ from pyedb.dotnet.clr_module import Array
8
+ from pyedb.dotnet.edb_core.edb_data.padstacks_data import (
9
+ EDBPadstack,
10
+ EDBPadstackInstance,
11
+ )
12
+ from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
13
+ from pyedb.generic.general_methods import generate_unique_name, pyedb_function_handler
14
+ from pyedb.modeler.geometry_operators import GeometryOperators
15
+
16
+
17
+ class EdbPadstacks(object):
18
+ """Manages EDB methods for nets management accessible from `Edb.padstacks` property.
19
+
20
+ Examples
21
+ --------
22
+ >>> from pyedb import Edb
23
+ >>> edbapp = Edb("myaedbfolder", edbversion="2021.2")
24
+ >>> edb_padstacks = edbapp.padstacks
25
+ """
26
+
27
+ @pyedb_function_handler()
28
+ def __getitem__(self, name):
29
+ """Get a padstack definition or instance from the Edb project.
30
+
31
+ Parameters
32
+ ----------
33
+ name : str, int
34
+
35
+ Returns
36
+ -------
37
+ :class:`pyedb.dotnet.edb_core.edb_data.components_data.EDBComponent`
38
+
39
+ """
40
+ if name in self.instances:
41
+ return self.instances[name]
42
+ elif name in self.definitions:
43
+ return self.definitions[name]
44
+ else:
45
+ for i in list(self.instances.values()):
46
+ if i.name == name or i.aedt_name == name:
47
+ return i
48
+ self._pedb.logger.error("Component or definition not found.")
49
+ return
50
+
51
+ def __init__(self, p_edb):
52
+ self._pedb = p_edb
53
+
54
+ @property
55
+ def _edb(self):
56
+ """ """
57
+ return self._pedb.edb_api
58
+
59
+ def _get_edb_value(self, value):
60
+ return self._pedb.edb_value(value)
61
+
62
+ @property
63
+ def _active_layout(self):
64
+ """ """
65
+ return self._pedb.active_layout
66
+
67
+ @property
68
+ def _layout(self):
69
+ """ """
70
+ return self._pedb.layout
71
+
72
+ @property
73
+ def db(self):
74
+ """Db object."""
75
+ return self._pedb.active_db
76
+
77
+ @property
78
+ def _logger(self):
79
+ """ """
80
+ return self._pedb.logger
81
+
82
+ @property
83
+ def _layers(self):
84
+ """ """
85
+ return self._pedb.stackup.stackup_layers
86
+
87
+ @pyedb_function_handler()
88
+ def int_to_pad_type(self, val=0):
89
+ """Convert an integer to an EDB.PadGeometryType.
90
+
91
+ Parameters
92
+ ----------
93
+ val : int
94
+
95
+ Returns
96
+ -------
97
+ object
98
+ EDB.PadType enumerator value.
99
+ """
100
+
101
+ if val == 0:
102
+ return self._edb.definition.PadType.RegularPad
103
+ elif val == 1:
104
+ return self._edb.definition.PadType.AntiPad
105
+ elif val == 2:
106
+ return self._edb.definition.PadType.ThermalPad
107
+ elif val == 3:
108
+ return self._edb.definition.PadType.Hole
109
+ elif val == 4:
110
+ return self._edb.definition.PadType.UnknownGeomType
111
+ else:
112
+ return val
113
+
114
+ @pyedb_function_handler()
115
+ def int_to_geometry_type(self, val=0):
116
+ """Convert an integer to an EDB.PadGeometryType.
117
+
118
+ Parameters
119
+ ----------
120
+ val : int
121
+
122
+ Returns
123
+ -------
124
+ object
125
+ EDB.PadGeometryType enumerator value.
126
+ """
127
+ if val == 0:
128
+ return self._edb.definition.PadGeometryType.NoGeometry
129
+ elif val == 1:
130
+ return self._edb.definition.PadGeometryType.Circle
131
+ elif val == 2:
132
+ return self._edb.definition.PadGeometryType.Square
133
+ elif val == 3:
134
+ return self._edb.definition.PadGeometryType.Rectangle
135
+ elif val == 4:
136
+ return self._edb.definition.PadGeometryType.Oval
137
+ elif val == 5:
138
+ return self._edb.definition.PadGeometryType.Bullet
139
+ elif val == 6:
140
+ return self._edb.definition.PadGeometryType.NSidedPolygon
141
+ elif val == 7:
142
+ return self._edb.definition.PadGeometryType.Polygon
143
+ elif val == 8:
144
+ return self._edb.definition.PadGeometryType.Round45
145
+ elif val == 9:
146
+ return self._edb.definition.PadGeometryType.Round90
147
+ elif val == 10:
148
+ return self._edb.definition.PadGeometryType.Square45
149
+ elif val == 11:
150
+ return self._edb.definition.PadGeometryType.Square90
151
+ else:
152
+ return val
153
+
154
+ @property
155
+ def definitions(self):
156
+ """Padstack definitions.
157
+
158
+ Returns
159
+ -------
160
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.padstacks_data.EdbPadstack`]
161
+ List of definitions via padstack definitions.
162
+
163
+ """
164
+ _padstacks = {}
165
+ for padstackdef in self._pedb.padstack_defs:
166
+ PadStackData = padstackdef.GetData()
167
+ if len(PadStackData.GetLayerNames()) >= 1:
168
+ _padstacks[padstackdef.GetName()] = EDBPadstack(padstackdef, self)
169
+ return _padstacks
170
+
171
+ @property
172
+ def padstacks(self):
173
+ """Padstacks via padstack definitions.
174
+
175
+ .. deprecated:: 0.6.58
176
+ Use :func:`definitions` property instead.
177
+
178
+ Returns
179
+ -------
180
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.EdbPadstack`]
181
+ List of definitions via padstack definitions.
182
+
183
+ """
184
+ warnings.warn("Use `definitions` property instead.", DeprecationWarning)
185
+ return self.definitions
186
+
187
+ @property
188
+ def instances(self):
189
+ """Dictionary of all padstack instances (vias and pins).
190
+
191
+ Returns
192
+ -------
193
+ dict[str, :class:`dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance`]
194
+ List of padstack instances.
195
+
196
+ """
197
+
198
+ padstack_instances = {}
199
+ edb_padstack_inst_list = self._pedb.layout.padstack_instances
200
+ for edb_padstack_instance in edb_padstack_inst_list:
201
+ padstack_instances[edb_padstack_instance.GetId()] = EDBPadstackInstance(edb_padstack_instance, self._pedb)
202
+ return padstack_instances
203
+
204
+ @property
205
+ def pins(self):
206
+ """Dictionary of all pins instances (belonging to component).
207
+
208
+ Returns
209
+ -------
210
+ dic[str, :class:`dotnet.edb_core.edb_data.definitions.EDBPadstackInstance`]
211
+ Dictionary of EDBPadstackInstance Components.
212
+
213
+
214
+ Examples
215
+ --------
216
+ >>> edbapp = dotnet.Edb("myproject.aedb")
217
+ >>> pin_net_name = edbapp.pins[424968329].netname
218
+ """
219
+ pins = {}
220
+ for instancename, instance in self.instances.items():
221
+ if instance.is_pin and instance.component:
222
+ pins[instancename] = instance
223
+ return pins
224
+
225
+ @property
226
+ def vias(self):
227
+ """Dictionary of all vias instances not belonging to component.
228
+
229
+ Returns
230
+ -------
231
+ dic[str, :class:`dotnet.edb_core.edb_data.definitions.EDBPadstackInstance`]
232
+ Dictionary of EDBPadstackInstance Components.
233
+
234
+
235
+ Examples
236
+ --------
237
+ >>> edbapp = dotnet.Edb("myproject.aedb")
238
+ >>> pin_net_name = edbapp.pins[424968329].netname
239
+ """
240
+ pnames = list(self.pins.keys())
241
+ vias = {i: j for i, j in self.instances.items() if i not in pnames}
242
+ return vias
243
+
244
+ @property
245
+ def padstack_instances(self):
246
+ """List of padstack instances.
247
+
248
+ .. deprecated:: 0.6.58
249
+ Use :func:`instances` property instead.
250
+
251
+ Returns
252
+ -------
253
+ dict[str, :class:`dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance`]
254
+ List of padstack instances.
255
+ """
256
+
257
+ warnings.warn("Use `instances` property instead.", DeprecationWarning)
258
+ return self.instances
259
+
260
+ @property
261
+ def pingroups(self):
262
+ """All Layout Pin groups.
263
+
264
+ Returns
265
+ -------
266
+ list
267
+ List of all layout pin groups.
268
+ """
269
+ pingroups = []
270
+ for el in self._layout.pin_groups:
271
+ pingroups.append(el)
272
+ return pingroups
273
+
274
+ @property
275
+ def pad_type(self):
276
+ """Return a PadType Enumerator."""
277
+
278
+ class PadType:
279
+ (RegularPad, AntiPad, ThermalPad, Hole, UnknownGeomType) = (
280
+ self._edb.definition.PadType.RegularPad,
281
+ self._edb.definition.PadType.AntiPad,
282
+ self._edb.definition.PadType.ThermalPad,
283
+ self._edb.definition.PadType.Hole,
284
+ self._edb.definition.PadType.UnknownGeomType,
285
+ )
286
+
287
+ return PadType
288
+
289
+ @pyedb_function_handler()
290
+ def create_circular_padstack(
291
+ self,
292
+ padstackname=None,
293
+ holediam="300um",
294
+ paddiam="400um",
295
+ antipaddiam="600um",
296
+ startlayer=None,
297
+ endlayer=None,
298
+ ):
299
+ """Create a circular padstack.
300
+
301
+ Parameters
302
+ ----------
303
+ padstackname : str, optional
304
+ Name of the padstack. The default is ``None``.
305
+ holediam : str, optional
306
+ Diameter of the hole with units. The default is ``"300um"``.
307
+ paddiam : str, optional
308
+ Diameter of the pad with units. The default is ``"400um"``.
309
+ antipaddiam : str, optional
310
+ Diameter of the antipad with units. The default is ``"600um"``.
311
+ startlayer : str, optional
312
+ Starting layer. The default is ``None``, in which case the top
313
+ is the starting layer.
314
+ endlayer : str, optional
315
+ Ending layer. The default is ``None``, in which case the bottom
316
+ is the ending layer.
317
+
318
+ Returns
319
+ -------
320
+ str
321
+ Name of the padstack if the operation is successful.
322
+ """
323
+
324
+ PadStack = self._edb.definition.PadstackDef.Create(self._layout.cell.GetDatabase(), padstackname)
325
+ new_PadStackData = self._edb.definition.PadstackDefData.Create()
326
+ list_values = convert_py_list_to_net_list(
327
+ [self._get_edb_value(holediam), self._get_edb_value(paddiam), self._get_edb_value(antipaddiam)]
328
+ )
329
+ value0 = self._get_edb_value(0.0)
330
+ new_PadStackData.SetHoleParameters(
331
+ self._edb.definition.PadGeometryType.Circle,
332
+ list_values,
333
+ value0,
334
+ value0,
335
+ value0,
336
+ )
337
+ new_PadStackData.SetHoleRange(self._edb.definition.PadstackHoleRange.UpperPadToLowerPad)
338
+ layers = list(self._pedb.stackup.signal_layers.keys())
339
+ if not startlayer:
340
+ startlayer = layers[0]
341
+ if not endlayer:
342
+ endlayer = layers[len(layers) - 1]
343
+
344
+ antipad_shape = self._edb.definition.PadGeometryType.Circle
345
+ started = False
346
+ new_PadStackData.SetPadParameters(
347
+ "Default",
348
+ self._edb.definition.PadType.RegularPad,
349
+ self._edb.definition.PadGeometryType.Circle,
350
+ convert_py_list_to_net_list([self._get_edb_value(paddiam)]),
351
+ value0,
352
+ value0,
353
+ value0,
354
+ )
355
+
356
+ new_PadStackData.SetPadParameters(
357
+ "Default",
358
+ self._edb.definition.PadType.AntiPad,
359
+ antipad_shape,
360
+ convert_py_list_to_net_list([self._get_edb_value(antipaddiam)]),
361
+ value0,
362
+ value0,
363
+ value0,
364
+ )
365
+ for layer in layers:
366
+ if layer == startlayer:
367
+ started = True
368
+ if layer == endlayer:
369
+ started = False
370
+ if started:
371
+ new_PadStackData.SetPadParameters(
372
+ layer,
373
+ self._edb.definition.PadType.RegularPad,
374
+ self._edb.definition.PadGeometryType.Circle,
375
+ convert_py_list_to_net_list([self._get_edb_value(paddiam)]),
376
+ value0,
377
+ value0,
378
+ value0,
379
+ )
380
+ new_PadStackData.SetPadParameters(
381
+ layer,
382
+ self._edb.definition.PadType.AntiPad,
383
+ antipad_shape,
384
+ convert_py_list_to_net_list([self._get_edb_value(antipaddiam)]),
385
+ value0,
386
+ value0,
387
+ value0,
388
+ )
389
+ PadStack.SetData(new_PadStackData)
390
+
391
+ @pyedb_function_handler()
392
+ def delete_padstack_instances(self, net_names): # pragma: no cover
393
+ """Delete padstack instances by net names.
394
+
395
+ Parameters
396
+ ----------
397
+ net_names : str, list
398
+ Names of the nets to delete.
399
+
400
+ Returns
401
+ -------
402
+ bool
403
+ ``True`` when successful, ``False`` when failed.
404
+
405
+ References
406
+ ----------
407
+
408
+ >>> Edb.padstacks.delete_padstack_instances(net_names=["GND"])
409
+ """
410
+ if not isinstance(net_names, list): # pragma: no cover
411
+ net_names = [net_names]
412
+
413
+ for p_id, p in self.instances.items():
414
+ if p.net_name in net_names:
415
+ if not p.delete(): # pragma: no cover
416
+ return False
417
+ return True
418
+
419
+ @pyedb_function_handler()
420
+ def set_solderball(self, padstackInst, sballLayer_name, isTopPlaced=True, ballDiam=100e-6):
421
+ """Set solderball for the given PadstackInstance.
422
+
423
+ Parameters
424
+ ----------
425
+ padstackInst : Edb.Cell.Primitive.PadstackInstance or int
426
+ Padstack instance id or object.
427
+ sballLayer_name : str,
428
+ Name of the layer where the solder ball is placed. No default values.
429
+ isTopPlaced : bool, optional.
430
+ Bollean triggering is the solder ball is placed on Top or Bottom of the layer stackup.
431
+ ballDiam : double, optional,
432
+ Solder ball diameter value.
433
+
434
+ Returns
435
+ -------
436
+ bool
437
+
438
+ """
439
+ if isinstance(padstackInst, int):
440
+ psdef = self.definitions[self.instances[padstackInst].padstack_definition].edb_padstack
441
+ padstackInst = self.instances[padstackInst]._edb_padstackinstance
442
+
443
+ else:
444
+ psdef = padstackInst.GetPadstackDef()
445
+ newdefdata = self._edb.definition.PadstackDefData(psdef.GetData())
446
+ newdefdata.SetSolderBallShape(self._edb.definition.SolderballShape.Cylinder)
447
+ newdefdata.SetSolderBallParameter(self._get_edb_value(ballDiam), self._get_edb_value(ballDiam))
448
+ sball_placement = (
449
+ self._edb.definition.SolderballPlacement.AbovePadstack
450
+ if isTopPlaced
451
+ else self._edb.definition.SolderballPlacement.BelowPadstack
452
+ )
453
+ newdefdata.SetSolderBallPlacement(sball_placement)
454
+ psdef.SetData(newdefdata)
455
+ sball_layer = [lay._edb_layer for lay in list(self._layers.values()) if lay.name == sballLayer_name][0]
456
+ if sball_layer is not None:
457
+ padstackInst.SetSolderBallLayer(sball_layer)
458
+ return True
459
+
460
+ return False
461
+
462
+ @pyedb_function_handler()
463
+ def create_coax_port(self, padstackinstance, use_dot_separator=True, name=None):
464
+ """Create HFSS 3Dlayout coaxial lumped port on a pastack
465
+ Requires to have solder ball defined before calling this method.
466
+
467
+ Parameters
468
+ ----------
469
+ padstackinstance : `Edb.Cell.Primitive.PadstackInstance` or int
470
+ Padstack instance object.
471
+ use_dot_separator : bool, optional
472
+ Whether to use ``.`` as the separator for the naming convention, which
473
+ is ``[component][net][pin]``. The default is ``True``. If ``False``, ``_`` is
474
+ used as the separator instead.
475
+ name : str
476
+ Port name for overwriting the default port-naming convention,
477
+ which is ``[component][net][pin]``. The port name must be unique.
478
+ If a port with the specified name already exists, the
479
+ default naming convention is used so that port creation does
480
+ not fail.
481
+
482
+ Returns
483
+ -------
484
+ str
485
+ Terminal name.
486
+
487
+ """
488
+ if isinstance(padstackinstance, int):
489
+ padstackinstance = self.instances[padstackinstance]._edb_padstackinstance
490
+ elif isinstance(padstackinstance, EDBPadstackInstance):
491
+ padstackinstance = padstackinstance._edb_padstackinstance
492
+ cmp_name = padstackinstance.GetComponent().GetName()
493
+ if cmp_name == "":
494
+ cmp_name = "no_comp"
495
+ net_name = padstackinstance.GetNet().GetName()
496
+ if net_name == "":
497
+ net_name = "no_net"
498
+ pin_name = padstackinstance.GetName()
499
+ if pin_name == "":
500
+ pin_name = "no_pin_name"
501
+ if use_dot_separator:
502
+ port_name = "{0}.{1}.{2}".format(cmp_name, pin_name, net_name)
503
+ else:
504
+ port_name = "{0}_{1}_{2}".format(cmp_name, pin_name, net_name)
505
+ if not padstackinstance.IsLayoutPin():
506
+ padstackinstance.SetIsLayoutPin(True)
507
+ res = padstackinstance.GetLayerRange()
508
+ if name:
509
+ port_name = name
510
+ if self._port_exist(port_name):
511
+ port_name = generate_unique_name(port_name, n=2)
512
+ self._logger.info("An existing port already has this same name. Renaming to {}.".format(port_name))
513
+ self._edb.cell.terminal.PadstackInstanceTerminal.Create(
514
+ self._active_layout,
515
+ padstackinstance.GetNet(),
516
+ port_name,
517
+ padstackinstance,
518
+ res[2],
519
+ )
520
+ if res[0]:
521
+ return port_name
522
+ return ""
523
+
524
+ @pyedb_function_handler()
525
+ def _port_exist(self, port_name):
526
+ return any(port for port in list(self._pedb.excitations.keys()) if port == port_name)
527
+
528
+ @pyedb_function_handler()
529
+ def get_pinlist_from_component_and_net(self, refdes=None, netname=None):
530
+ """Retrieve pins given a component's reference designator and net name.
531
+
532
+ Parameters
533
+ ----------
534
+ refdes : str, optional
535
+ Reference designator of the component. The default is ``None``.
536
+ netname : str optional
537
+ Name of the net. The default is ``None``.
538
+
539
+ Returns
540
+ -------
541
+ dict
542
+ Dictionary of pins if the operation is successful.
543
+ ``False`` is returned if the net does not belong to the component.
544
+
545
+ """
546
+ pinlist = []
547
+ if refdes:
548
+ if refdes in self._pedb.components.components:
549
+ if netname:
550
+ for pin, val in self._pedb.components.components[refdes].pins.items():
551
+ if val.net_name == netname:
552
+ pinlist.append(val)
553
+ else:
554
+ for pin in self._pedb.components.components[refdes].pins.values():
555
+ pinlist.append(pin)
556
+ elif netname:
557
+ for pin in self._pedb.pins:
558
+ if pin.net_name == netname:
559
+ pinlist.append(pin)
560
+ else:
561
+ self._logger.error("At least a component or a net name has to be provided")
562
+
563
+ return pinlist
564
+
565
+ @pyedb_function_handler()
566
+ def get_pad_parameters(self, pin, layername, pad_type=0):
567
+ """Get Padstack Parameters from Pin or Padstack Definition.
568
+
569
+ Parameters
570
+ ----------
571
+ pin : Edb.definition.PadstackDef or Edb.definition.PadstackInstance
572
+ Pin or PadstackDef on which get values.
573
+ layername : str
574
+ Layer on which get properties.
575
+ pad_type : int
576
+ Pad Type.
577
+
578
+ Returns
579
+ -------
580
+ tuple
581
+ Tuple of (GeometryType, ParameterList, OffsetX, OffsetY, Rot).
582
+ """
583
+
584
+ if "PadstackDef" in str(type(pin)):
585
+ padparams = pin.GetData().GetPadParametersValue(layername, self.int_to_pad_type(pad_type))
586
+ else:
587
+ padparams = self._edb.definition.PadstackDefData(pin.GetPadstackDef().GetData()).GetPadParametersValue(
588
+ layername, self.int_to_pad_type(pad_type)
589
+ )
590
+ if padparams[2]:
591
+ geometry_type = int(padparams[1])
592
+ parameters = [i.ToString() for i in padparams[2]]
593
+ offset_x = padparams[3].ToDouble()
594
+ offset_y = padparams[4].ToDouble()
595
+ rotation = padparams[5].ToDouble()
596
+ return geometry_type, parameters, offset_x, offset_y, rotation
597
+ else:
598
+ if isinstance(pin, self._edb.definition.PadstackDef):
599
+ padparams = self._edb.definition.PadstackDefData(pin.GetData()).GetPolygonalPadParameters(
600
+ layername, self.int_to_pad_type(pad_type)
601
+ )
602
+ else:
603
+ padparams = self._edb.definition.PadstackDefData(
604
+ pin.GetPadstackDef().GetData()
605
+ ).GetPolygonalPadParameters(layername, self.int_to_pad_type(pad_type))
606
+
607
+ if padparams[0]:
608
+ parameters = [
609
+ padparams[1].GetBBox().Item1.X.ToDouble(),
610
+ padparams[1].GetBBox().Item1.Y.ToDouble(),
611
+ padparams[1].GetBBox().Item2.X.ToDouble(),
612
+ padparams[1].GetBBox().Item2.Y.ToDouble(),
613
+ ]
614
+ offset_x = padparams[2]
615
+ offset_y = padparams[3]
616
+ rotation = padparams[4]
617
+ geometry_type = 7
618
+ return geometry_type, parameters, offset_x, offset_y, rotation
619
+ return 0, [0], 0, 0, 0
620
+
621
+ @pyedb_function_handler()
622
+ def set_all_antipad_value(self, value):
623
+ """Set all anti-pads from all pad-stack definition to the given value.
624
+
625
+ Parameters
626
+ ----------
627
+ value : float, str
628
+ Anti-pad value.
629
+
630
+ Returns
631
+ -------
632
+ bool
633
+ ``True`` when successful, ``False`` if an anti-pad value fails to be assigned.
634
+ """
635
+ if self.definitions:
636
+ for padstack in list(self.definitions.values()):
637
+ cloned_padstack_data = self._edb.definition.PadstackDefData(padstack.edb_padstack.GetData())
638
+ layers_name = cloned_padstack_data.GetLayerNames()
639
+ all_succeed = True
640
+ for layer in layers_name:
641
+ geom_type, parameters, offset_x, offset_y, rot = self.get_pad_parameters(
642
+ padstack.edb_padstack, layer, 1
643
+ )
644
+ if geom_type == 1: # pragma no cover
645
+ params = convert_py_list_to_net_list(
646
+ [self._pedb.edb_value(value)] * len(parameters)
647
+ ) # pragma no cover
648
+ geom = self._edb.definition.PadGeometryType.Circle
649
+ offset_x = self._pedb.edb_value(offset_x)
650
+ offset_y = self._pedb.edb_value(offset_y)
651
+ rot = self._pedb.edb_value(rot)
652
+ antipad = self._edb.definition.PadType.AntiPad
653
+ if cloned_padstack_data.SetPadParameters(
654
+ layer, antipad, geom, params, offset_x, offset_y, rot
655
+ ): # pragma no cover
656
+ self._logger.info(
657
+ "Pad-stack definition {}, anti-pad on layer {}, has been set to {}".format(
658
+ padstack.edb_padstack.GetName(), layer, str(value)
659
+ )
660
+ )
661
+ else: # pragma no cover
662
+ self._logger.error(
663
+ "Failed to reassign anti-pad value {} on Pads-stack definition {},"
664
+ " layer{}".format(str(value), padstack.edb_padstack.GetName(), layer)
665
+ )
666
+ all_succeed = False
667
+ padstack.edb_padstack.SetData(cloned_padstack_data)
668
+ return all_succeed
669
+
670
+ @pyedb_function_handler()
671
+ def check_and_fix_via_plating(self, minimum_value_to_replace=0.0, default_plating_ratio=0.2):
672
+ """Check for minimum via plating ration value, values found below the minimum one are replaced by default
673
+ plating ratio.
674
+
675
+ Parameters
676
+ ----------
677
+ minimum_value_to_replace : float
678
+ Plating ratio that is below or equal to this value is to be replaced
679
+ with the value specified for the next parameter. Default value ``0.0``.
680
+ default_plating_ratio : float
681
+ Default value to use for plating ratio. The default value is ``0.2``.
682
+
683
+ Returns
684
+ -------
685
+ bool
686
+ ``True`` when successful, ``False`` if an anti-pad value fails to be assigned.
687
+ """
688
+ for padstack_def in list(self.definitions.values()):
689
+ if padstack_def.hole_plating_ratio <= minimum_value_to_replace:
690
+ padstack_def.hole_plating_ratio = default_plating_ratio
691
+ self._logger.info(
692
+ "Padstack definition with zero plating ratio, defaulting to 20%".format(padstack_def.name)
693
+ )
694
+ return True
695
+
696
+ @pyedb_function_handler()
697
+ def get_via_instance_from_net(self, net_list=None):
698
+ """Get the list for EDB vias from a net name list.
699
+
700
+ Parameters
701
+ ----------
702
+ net_list : str or list
703
+ The list of the net name to be used for filtering vias. If no net is provided the command will
704
+ return an all vias list.
705
+
706
+ Returns
707
+ -------
708
+ list of Edb.Cell.Primitive.PadstackInstance
709
+ List of EDB vias.
710
+ """
711
+ if net_list == None:
712
+ net_list = []
713
+
714
+ if not isinstance(net_list, list):
715
+ net_list = [net_list]
716
+ layout_lobj_collection = self._layout.padstack_instances
717
+ via_list = []
718
+ for lobj in layout_lobj_collection:
719
+ pad_layers_name = lobj.GetPadstackDef().GetData().GetLayerNames()
720
+ if len(pad_layers_name) > 1:
721
+ if not net_list:
722
+ via_list.append(lobj)
723
+ elif lobj.GetNet().GetName() in net_list:
724
+ via_list.append(lobj)
725
+ return via_list
726
+
727
+ @pyedb_function_handler()
728
+ def create_padstack(
729
+ self,
730
+ padstackname=None,
731
+ holediam="300um",
732
+ paddiam="400um",
733
+ antipaddiam="600um",
734
+ startlayer=None,
735
+ endlayer=None,
736
+ antipad_shape="Circle",
737
+ x_size="600um",
738
+ y_size="600um",
739
+ corner_radius="300um",
740
+ offset_x="0.0",
741
+ offset_y="0.0",
742
+ rotation="0.0",
743
+ has_hole=True,
744
+ pad_offset_x="0.0",
745
+ pad_offset_y="0.0",
746
+ pad_rotation="0.0",
747
+ ): # pragma: no cover
748
+ """Create a padstack.
749
+
750
+ .. deprecated:: 0.6.62
751
+ Use :func:`create` method instead.
752
+
753
+ Parameters
754
+ ----------
755
+ padstackname : str, optional
756
+ Name of the padstack. The default is ``None``.
757
+ holediam : str, optional
758
+ Diameter of the hole with units. The default is ``"300um"``.
759
+ paddiam : str, optional
760
+ Diameter of the pad with units. The default is ``"400um"``.
761
+ antipaddiam : str, optional
762
+ Diameter of the antipad with units. The default is ``"600um"``.
763
+ startlayer : str, optional
764
+ Starting layer. The default is ``None``, in which case the top
765
+ is the starting layer.
766
+ endlayer : str, optional
767
+ Ending layer. The default is ``None``, in which case the bottom
768
+ is the ending layer.
769
+ antipad_shape : str, optional
770
+ Shape of the antipad. The default is ``"Circle"``. Options are ``"Circle"`` and ``"Bullet"``.
771
+ x_size : str, optional
772
+ Only applicable to bullet shape. The default is ``"600um"``.
773
+ y_size : str, optional
774
+ Only applicable to bullet shape. The default is ``"600um"``.
775
+ corner_radius :
776
+ Only applicable to bullet shape. The default is ``"300um"``.
777
+ offset_x : str, optional
778
+ X offset of antipad. The default is ``"0.0"``.
779
+ offset_y : str, optional
780
+ Y offset of antipad. The default is ``"0.0"``.
781
+ rotation : str, optional
782
+ rotation of antipad. The default is ``"0.0"``.
783
+ has_hole : bool, optional
784
+ Whether this padstack has a hole.
785
+
786
+ Returns
787
+ -------
788
+ str
789
+ Name of the padstack if the operation is successful.
790
+ """
791
+ warnings.warn("Use :func:`create` method instead.", DeprecationWarning)
792
+ return self.create(
793
+ padstackname=padstackname,
794
+ holediam=holediam,
795
+ paddiam=paddiam,
796
+ antipaddiam=antipaddiam,
797
+ antipad_shape=antipad_shape,
798
+ x_size=x_size,
799
+ y_size=y_size,
800
+ corner_radius=corner_radius,
801
+ offset_x=offset_x,
802
+ offset_y=offset_y,
803
+ rotation=rotation,
804
+ has_hole=has_hole,
805
+ pad_offset_x=pad_offset_x,
806
+ pad_offset_y=pad_offset_y,
807
+ pad_rotation=pad_rotation,
808
+ )
809
+
810
+ @pyedb_function_handler()
811
+ def create(
812
+ self,
813
+ padstackname=None,
814
+ holediam="300um",
815
+ paddiam="400um",
816
+ antipaddiam="600um",
817
+ pad_shape="Circle",
818
+ antipad_shape="Circle",
819
+ x_size="600um",
820
+ y_size="600um",
821
+ corner_radius="300um",
822
+ offset_x="0.0",
823
+ offset_y="0.0",
824
+ rotation="0.0",
825
+ has_hole=True,
826
+ pad_offset_x="0.0",
827
+ pad_offset_y="0.0",
828
+ pad_rotation="0.0",
829
+ start_layer=None,
830
+ stop_layer=None,
831
+ add_default_layer=False,
832
+ anti_pad_x_size="600um",
833
+ anti_pad_y_size="600um",
834
+ hole_range="upper_pad_to_lower_pad",
835
+ ):
836
+ """Create a padstack.
837
+
838
+ Parameters
839
+ ----------
840
+ padstackname : str, optional
841
+ Name of the padstack. The default is ``None``.
842
+ holediam : str, optional
843
+ Diameter of the hole with units. The default is ``"300um"``.
844
+ paddiam : str, optional
845
+ Diameter of the pad with units, used with ``"Circle"`` shape. The default is ``"400um"``.
846
+ antipaddiam : str, optional
847
+ Diameter of the antipad with units. The default is ``"600um"``.
848
+ pad_shape : str, optional
849
+ Shape of the pad. The default is ``"Circle``. Options are ``"Circle"`` and ``"Rectangle"``.
850
+ antipad_shape : str, optional
851
+ Shape of the antipad. The default is ``"Circle"``. Options are ``"Circle"`` ``"Rectangle"`` and
852
+ ``"Bullet"``.
853
+ x_size : str, optional
854
+ Only applicable to bullet and rectangle shape. The default is ``"600um"``.
855
+ y_size : str, optional
856
+ Only applicable to bullet and rectangle shape. The default is ``"600um"``.
857
+ corner_radius :
858
+ Only applicable to bullet shape. The default is ``"300um"``.
859
+ offset_x : str, optional
860
+ X offset of antipad. The default is ``"0.0"``.
861
+ offset_y : str, optional
862
+ Y offset of antipad. The default is ``"0.0"``.
863
+ rotation : str, optional
864
+ rotation of antipad. The default is ``"0.0"``.
865
+ has_hole : bool, optional
866
+ Whether this padstack has a hole.
867
+ pad_offset_x : str, optional
868
+ Padstack offset in X direction.
869
+ pad_offset_y : str, optional
870
+ Padstack offset in Y direction.
871
+ pad_rotation : str, optional
872
+ Padstack rotation.
873
+ start_layer : str, optional
874
+ Start layer of the padstack definition.
875
+ stop_layer : str, optional
876
+ Stop layer of the padstack definition.
877
+ add_default_layer : bool, optional
878
+ Add ``"Default"`` to padstack definition. Default is ``False``.
879
+ anti_pad_x_size : str, optional
880
+ Only applicable to bullet and rectangle shape. The default is ``"600um"``.
881
+ anti_pad_y_size : str, optional
882
+ Only applicable to bullet and rectangle shape. The default is ``"600um"``.
883
+ hole_range : str, optional
884
+ Define the padstack hole range. Arguments supported, ``"through"``, ``"begin_on_upper_pad"``,
885
+ ``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``.
886
+
887
+ Returns
888
+ -------
889
+ str
890
+ Name of the padstack if the operation is successful.
891
+ """
892
+ holediam = self._get_edb_value(holediam)
893
+ paddiam = self._get_edb_value(paddiam)
894
+ antipaddiam = self._get_edb_value(antipaddiam)
895
+
896
+ if not padstackname:
897
+ padstackname = generate_unique_name("VIA")
898
+ # assert not self.isreadonly, "Write Functions are not available within AEDT"
899
+ padstackData = self._edb.definition.PadstackDefData.Create()
900
+ if has_hole:
901
+ ptype = self._edb.definition.PadGeometryType.Circle
902
+ else:
903
+ ptype = self._edb.definition.PadGeometryType.NoGeometry
904
+ holparam = Array[type(holediam)]([holediam])
905
+ value0 = self._get_edb_value("0.0")
906
+ x_size = self._get_edb_value(x_size)
907
+ y_size = self._get_edb_value(y_size)
908
+ corner_radius = self._get_edb_value(corner_radius)
909
+ offset_x = self._get_edb_value(offset_x)
910
+ offset_y = self._get_edb_value(offset_y)
911
+ rotation = self._get_edb_value(rotation)
912
+
913
+ pad_offset_x = self._get_edb_value(pad_offset_x)
914
+ pad_offset_y = self._get_edb_value(pad_offset_y)
915
+ pad_rotation = self._get_edb_value(pad_rotation)
916
+ anti_pad_x_size = self._get_edb_value(anti_pad_x_size)
917
+ anti_pad_y_size = self._get_edb_value(anti_pad_y_size)
918
+ padstackData.SetHoleParameters(ptype, holparam, value0, value0, value0)
919
+ padstackData.SetHolePlatingPercentage(self._get_edb_value(20.0))
920
+ if hole_range == "through": # pragma no cover
921
+ padstackData.SetHoleRange(self._edb.definition.PadstackHoleRange.Through)
922
+ elif hole_range == "begin_on_upper_pad": # pragma no cover
923
+ padstackData.SetHoleRange(self._edb.definition.PadstackHoleRange.BeginOnUpperPad)
924
+ elif hole_range == "end_on_lower_pad": # pragma no cover
925
+ padstackData.SetHoleRange(self._edb.definition.PadstackHoleRange.EndOnLowerPad)
926
+ elif hole_range == "upper_pad_to_lower_pad": # pragma no cover
927
+ padstackData.SetHoleRange(self._edb.definition.PadstackHoleRange.UpperPadToLowerPad)
928
+ else: # pragma no cover
929
+ self._logger.error("Unknown padstack hole range")
930
+ padstackData.SetMaterial("copper")
931
+ layers = list(self._pedb.stackup.signal_layers.keys())[:]
932
+ if start_layer and start_layer in layers: # pragma no cover
933
+ layers = layers[layers.index(start_layer) :]
934
+ if stop_layer and stop_layer in layers: # pragma no cover
935
+ layers = layers[: layers.index(stop_layer) + 1]
936
+ pad_array = Array[type(paddiam)]([paddiam])
937
+ if pad_shape == "Circle": # pragma no cover
938
+ pad_shape = self._edb.definition.PadGeometryType.Circle
939
+ elif pad_shape == "Rectangle": # pragma no cover
940
+ pad_array = Array[type(x_size)]([x_size, y_size])
941
+ pad_shape = self._edb.definition.PadGeometryType.Rectangle
942
+ if antipad_shape == "Bullet": # pragma no cover
943
+ antipad_array = Array[type(x_size)]([x_size, y_size, corner_radius])
944
+ antipad_shape = self._edb.definition.PadGeometryType.Bullet
945
+ elif antipad_shape == "Rectangle": # pragma no cover
946
+ antipad_array = Array[type(anti_pad_x_size)]([anti_pad_x_size, anti_pad_y_size])
947
+ antipad_shape = self._edb.definition.PadGeometryType.Rectangle
948
+ else: # pragma no cover
949
+ antipad_array = Array[type(antipaddiam)]([antipaddiam])
950
+ antipad_shape = self._edb.definition.PadGeometryType.Circle
951
+ if add_default_layer: # pragma no cover
952
+ layers = layers + ["Default"]
953
+ for layer in layers:
954
+ padstackData.SetPadParameters(
955
+ layer,
956
+ self._edb.definition.PadType.RegularPad,
957
+ pad_shape,
958
+ pad_array,
959
+ pad_offset_x,
960
+ pad_offset_y,
961
+ pad_rotation,
962
+ )
963
+
964
+ padstackData.SetPadParameters(
965
+ layer,
966
+ self._edb.definition.PadType.AntiPad,
967
+ antipad_shape,
968
+ antipad_array,
969
+ offset_x,
970
+ offset_y,
971
+ rotation,
972
+ )
973
+
974
+ padstackDefinition = self._edb.definition.PadstackDef.Create(self.db, padstackname)
975
+ padstackDefinition.SetData(padstackData)
976
+ self._logger.info("Padstack %s create correctly", padstackname)
977
+ return padstackname
978
+
979
+ @pyedb_function_handler()
980
+ def _get_pin_layer_range(self, pin):
981
+ res, fromlayer, tolayer = pin.GetLayerRange()
982
+ if res:
983
+ return fromlayer, tolayer
984
+ else:
985
+ return False
986
+
987
+ @pyedb_function_handler()
988
+ def duplicate_padstack(self, target_padstack_name, new_padstack_name=""):
989
+ """Duplicate a padstack.
990
+
991
+ .. deprecated:: 0.6.62
992
+ Use :func:`duplicate` method instead.
993
+
994
+ Parameters
995
+ ----------
996
+ target_padstack_name : str
997
+ Name of the padstack to be duplicated.
998
+ new_padstack_name : str, optional
999
+ Name of the new padstack.
1000
+
1001
+ Returns
1002
+ -------
1003
+ str
1004
+ Name of the new padstack.
1005
+ """
1006
+ warnings.warn("Use :func:`create` method instead.", DeprecationWarning)
1007
+ return self.duplicate(target_padstack_name=target_padstack_name, new_padstack_name=new_padstack_name)
1008
+
1009
+ @pyedb_function_handler()
1010
+ def duplicate(self, target_padstack_name, new_padstack_name=""):
1011
+ """Duplicate a padstack.
1012
+
1013
+ Parameters
1014
+ ----------
1015
+ target_padstack_name : str
1016
+ Name of the padstack to be duplicated.
1017
+ new_padstack_name : str, optional
1018
+ Name of the new padstack.
1019
+
1020
+ Returns
1021
+ -------
1022
+ str
1023
+ Name of the new padstack.
1024
+ """
1025
+ p1 = self.definitions[target_padstack_name].edb_padstack.GetData()
1026
+ new_padstack_definition_data = self._edb.definition.PadstackDefData(p1)
1027
+
1028
+ if not new_padstack_name:
1029
+ new_padstack_name = generate_unique_name(target_padstack_name)
1030
+
1031
+ padstack_definition = self._edb.definition.PadstackDef.Create(self.db, new_padstack_name)
1032
+ padstack_definition.SetData(new_padstack_definition_data)
1033
+
1034
+ return new_padstack_name
1035
+
1036
+ @pyedb_function_handler()
1037
+ def place(
1038
+ self,
1039
+ position,
1040
+ definition_name,
1041
+ net_name="",
1042
+ via_name="",
1043
+ rotation=0.0,
1044
+ fromlayer=None,
1045
+ tolayer=None,
1046
+ solderlayer=None,
1047
+ is_pin=False,
1048
+ ):
1049
+ """Place a via.
1050
+
1051
+ Parameters
1052
+ ----------
1053
+ position : list
1054
+ List of float values for the [x,y] positions where the via is to be placed.
1055
+ definition_name : str
1056
+ Name of the padstack definition.
1057
+ net_name : str, optional
1058
+ Name of the net. The default is ``""``.
1059
+ via_name : str, optional
1060
+ The default is ``""``.
1061
+ rotation : float, optional
1062
+ Rotation of the padstack in degrees. The default
1063
+ is ``0``.
1064
+ fromlayer :
1065
+ The default is ``None``.
1066
+ tolayer :
1067
+ The default is ``None``.
1068
+ solderlayer :
1069
+ The default is ``None``.
1070
+ is_pin : bool, optional
1071
+ Whether if the padstack is a pin or not. Default is `False`.
1072
+
1073
+ Returns
1074
+ -------
1075
+ :class:`dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance`
1076
+ """
1077
+ padstack = None
1078
+ for pad in list(self.definitions.keys()):
1079
+ if pad == definition_name:
1080
+ padstack = self.definitions[pad].edb_padstack
1081
+ position = self._edb.geometry.point_data(position[0], position[1])
1082
+ net = self._pedb.nets.find_or_create_net(net_name)
1083
+ rotation = self._get_edb_value(rotation * math.pi / 180)
1084
+ sign_layers_values = {i: v for i, v in self._pedb.stackup.signal_layers.items()}
1085
+ sign_layers = list(sign_layers_values.keys())
1086
+ if not fromlayer:
1087
+ try:
1088
+ fromlayer = sign_layers_values[list(self.definitions[pad].pad_by_layer.keys())[0]]._edb_layer
1089
+ except KeyError:
1090
+ fromlayer = sign_layers_values[sign_layers[0]]._edb_layer
1091
+ else:
1092
+ fromlayer = sign_layers_values[fromlayer]._edb_layer
1093
+
1094
+ if not tolayer:
1095
+ try:
1096
+ tolayer = sign_layers_values[list(self.definitions[pad].pad_by_layer.keys())[-1]]._edb_layer
1097
+ except KeyError:
1098
+ tolayer = sign_layers_values[sign_layers[-1]]._edb_layer
1099
+ else:
1100
+ tolayer = sign_layers_values[tolayer]._edb_layer
1101
+ if solderlayer:
1102
+ solderlayer = sign_layers_values[solderlayer]._edb_layer
1103
+ if padstack:
1104
+ padstack_instance = self._edb.cell.primitive.padstack_instance.create(
1105
+ self._active_layout,
1106
+ net,
1107
+ via_name,
1108
+ padstack,
1109
+ position,
1110
+ rotation,
1111
+ fromlayer,
1112
+ tolayer,
1113
+ solderlayer,
1114
+ None,
1115
+ )
1116
+ padstack_instance.SetIsLayoutPin(is_pin)
1117
+ py_padstack_instance = EDBPadstackInstance(padstack_instance.api_object, self._pedb)
1118
+
1119
+ return py_padstack_instance
1120
+ else:
1121
+ return False
1122
+
1123
+ @pyedb_function_handler()
1124
+ def place_padstack(
1125
+ self,
1126
+ position,
1127
+ definition_name,
1128
+ net_name="",
1129
+ via_name="",
1130
+ rotation=0.0,
1131
+ fromlayer=None,
1132
+ tolayer=None,
1133
+ solderlayer=None,
1134
+ is_pin=False,
1135
+ ):
1136
+ """Place the padstack.
1137
+
1138
+ .. deprecated:: 0.6.62
1139
+ Use :func:`place` method instead.
1140
+
1141
+ Parameters
1142
+ ----------
1143
+ position : list
1144
+ List of float values for the [x,y] positions where the via is to be placed.
1145
+ definition_name : str
1146
+ Name of the padstack definition.
1147
+ net_name : str, optional
1148
+ Name of the net. The default is ``""``.
1149
+ via_name : str, optional
1150
+ The default is ``""``.
1151
+ rotation : float, optional
1152
+ Rotation of the padstack in degrees. The default
1153
+ is ``0``.
1154
+ fromlayer :
1155
+ The default is ``None``.
1156
+ tolayer :
1157
+ The default is ``None``.
1158
+ solderlayer :
1159
+ The default is ``None``.
1160
+
1161
+ Returns
1162
+ -------
1163
+
1164
+ """
1165
+ warnings.warn(" Use :func:`place` method instead.", DeprecationWarning)
1166
+ return self.place(
1167
+ position=position,
1168
+ definition_name=definition_name,
1169
+ net_name=net_name,
1170
+ via_name=via_name,
1171
+ rotation=rotation,
1172
+ fromlayer=fromlayer,
1173
+ tolayer=tolayer,
1174
+ solderlayer=solderlayer,
1175
+ is_pin=is_pin,
1176
+ )
1177
+
1178
+ @pyedb_function_handler()
1179
+ def remove_pads_from_padstack(self, padstack_name, layer_name=None):
1180
+ """Remove the Pad from a padstack on a specific layer by setting it as a 0 thickness circle.
1181
+
1182
+ Parameters
1183
+ ----------
1184
+ padstack_name : str
1185
+ padstack name
1186
+ layer_name : str, optional
1187
+ Layer name on which remove the PadParameters. If None, all layers will be taken.
1188
+
1189
+ Returns
1190
+ -------
1191
+ bool
1192
+ ``True`` if successful.
1193
+ """
1194
+ pad_type = self._edb.definition.PadType.RegularPad
1195
+ pad_geo = self._edb.definition.PadGeometryType.Circle
1196
+ vals = self._get_edb_value(0)
1197
+ params = convert_py_list_to_net_list([self._get_edb_value(0)])
1198
+ p1 = self.definitions[padstack_name].edb_padstack.GetData()
1199
+ newPadstackDefinitionData = self._edb.definition.PadstackDefData(p1)
1200
+
1201
+ if not layer_name:
1202
+ layer_name = list(self._pedb.stackup.signal_layers.keys())
1203
+ elif isinstance(layer_name, str):
1204
+ layer_name = [layer_name]
1205
+ for lay in layer_name:
1206
+ newPadstackDefinitionData.SetPadParameters(lay, pad_type, pad_geo, params, vals, vals, vals)
1207
+
1208
+ self.definitions[padstack_name].edb_padstack.SetData(newPadstackDefinitionData)
1209
+ return True
1210
+
1211
+ @pyedb_function_handler()
1212
+ def set_pad_property(
1213
+ self,
1214
+ padstack_name,
1215
+ layer_name=None,
1216
+ pad_shape="Circle",
1217
+ pad_params=0,
1218
+ pad_x_offset=0,
1219
+ pad_y_offset=0,
1220
+ pad_rotation=0,
1221
+ antipad_shape="Circle",
1222
+ antipad_params=0,
1223
+ antipad_x_offset=0,
1224
+ antipad_y_offset=0,
1225
+ antipad_rotation=0,
1226
+ ):
1227
+ """Set pad and antipad properties of the padstack.
1228
+
1229
+ Parameters
1230
+ ----------
1231
+ padstack_name : str
1232
+ Name of the padstack.
1233
+ layer_name : str, optional
1234
+ Name of the layer. If None, all layers will be taken.
1235
+ pad_shape : str, optional
1236
+ Shape of the pad. The default is ``"Circle"``. Options are ``"Circle"``, ``"Square"``, ``"Rectangle"``,
1237
+ ``"Oval"`` and ``"Bullet"``.
1238
+ pad_params : str, optional
1239
+ Dimension of the pad. The default is ``"0"``.
1240
+ pad_x_offset : str, optional
1241
+ X offset of the pad. The default is ``"0"``.
1242
+ pad_y_offset : str, optional
1243
+ Y offset of the pad. The default is ``"0"``.
1244
+ pad_rotation : str, optional
1245
+ Rotation of the pad. The default is ``"0"``.
1246
+ antipad_shape : str, optional
1247
+ Shape of the antipad. The default is ``"0"``.
1248
+ antipad_params : str, optional
1249
+ Dimension of the antipad. The default is ``"0"``.
1250
+ antipad_x_offset : str, optional
1251
+ X offset of the antipad. The default is ``"0"``.
1252
+ antipad_y_offset : str, optional
1253
+ Y offset of the antipad. The default is ``"0"``.
1254
+ antipad_rotation : str, optional
1255
+ Rotation of the antipad. The default is ``"0"``.
1256
+
1257
+ Returns
1258
+ -------
1259
+ bool
1260
+ ``True`` if successful.
1261
+ """
1262
+ shape_dict = {
1263
+ "Circle": self._edb.definition.PadGeometryType.Circle,
1264
+ "Square": self._edb.definition.PadGeometryType.Square,
1265
+ "Rectangle": self._edb.definition.PadGeometryType.Rectangle,
1266
+ "Oval": self._edb.definition.PadGeometryType.Oval,
1267
+ "Bullet": self._edb.definition.PadGeometryType.Bullet,
1268
+ }
1269
+ pad_shape = shape_dict[pad_shape]
1270
+ if not isinstance(pad_params, list):
1271
+ pad_params = [pad_params]
1272
+ pad_params = convert_py_list_to_net_list([self._get_edb_value(i) for i in pad_params])
1273
+ pad_x_offset = self._get_edb_value(pad_x_offset)
1274
+ pad_y_offset = self._get_edb_value(pad_y_offset)
1275
+ pad_rotation = self._get_edb_value(pad_rotation)
1276
+
1277
+ antipad_shape = shape_dict[antipad_shape]
1278
+ if not isinstance(antipad_params, list):
1279
+ antipad_params = [antipad_params]
1280
+ antipad_params = convert_py_list_to_net_list([self._get_edb_value(i) for i in antipad_params])
1281
+ antipad_x_offset = self._get_edb_value(antipad_x_offset)
1282
+ antipad_y_offset = self._get_edb_value(antipad_y_offset)
1283
+ antipad_rotation = self._get_edb_value(antipad_rotation)
1284
+
1285
+ p1 = self.definitions[padstack_name].edb_padstack.GetData()
1286
+ new_padstack_def = self._edb.definition.PadstackDefData(p1)
1287
+ if not layer_name:
1288
+ layer_name = list(self._pedb.stackup.signal_layers.keys())
1289
+ elif isinstance(layer_name, str):
1290
+ layer_name = [layer_name]
1291
+ for layer in layer_name:
1292
+ new_padstack_def.SetPadParameters(
1293
+ layer,
1294
+ self._edb.definition.PadType.RegularPad,
1295
+ pad_shape,
1296
+ pad_params,
1297
+ pad_x_offset,
1298
+ pad_y_offset,
1299
+ pad_rotation,
1300
+ )
1301
+ new_padstack_def.SetPadParameters(
1302
+ layer,
1303
+ self._edb.definition.PadType.AntiPad,
1304
+ antipad_shape,
1305
+ antipad_params,
1306
+ antipad_x_offset,
1307
+ antipad_y_offset,
1308
+ antipad_rotation,
1309
+ )
1310
+ self.definitions[padstack_name].edb_padstack.SetData(new_padstack_def)
1311
+ return True
1312
+
1313
+ @pyedb_function_handler()
1314
+ def get_padstack_instance_by_net_name(self, net_name):
1315
+ """Get a list of padstack instances by net name.
1316
+
1317
+ Parameters
1318
+ ----------
1319
+ net_name : str
1320
+ The net name to be used for filtering padstack instances.
1321
+
1322
+ Returns
1323
+ -------
1324
+ list
1325
+ List of :class:`dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance`.
1326
+ """
1327
+ padstack_instances = []
1328
+ for inst_id, inst in self.instances.items():
1329
+ if inst.net_name == net_name:
1330
+ padstack_instances.append(inst)
1331
+ return padstack_instances
1332
+
1333
+ @pyedb_function_handler()
1334
+ def get_reference_pins(
1335
+ self, positive_pin, reference_net="gnd", search_radius=5e-3, max_limit=0, component_only=True
1336
+ ):
1337
+ """Search for reference pins using given criteria.
1338
+
1339
+ Parameters
1340
+ ----------
1341
+ positive_pin : EDBPadstackInstance
1342
+ Pin used for evaluating the distance on the reference pins found.
1343
+ reference_net : str, optional
1344
+ Reference net. The default is ``"gnd"``.
1345
+ search_radius : float, optional
1346
+ Search radius for finding padstack instances. The default is ``5e-3``.
1347
+ max_limit : int, optional
1348
+ Maximum limit for the padstack instances found. The default is ``0``, in which
1349
+ case no limit is applied. The maximum limit value occurs on the nearest
1350
+ reference pins from the positive one that is found.
1351
+ component_only : bool, optional
1352
+ Whether to limit the search to component padstack instances only. The
1353
+ default is ``True``. When ``False``, the search is extended to the entire layout.
1354
+
1355
+ Returns
1356
+ -------
1357
+ list
1358
+ List of :class:`dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance`.
1359
+
1360
+ Examples
1361
+ --------
1362
+ >>> edbapp = Edb("target_path")
1363
+ >>> pin = edbapp.components.instances["J5"].pins["19"]
1364
+ >>> reference_pins = edbapp.padstacks.get_reference_pins(positive_pin=pin, reference_net="GND",
1365
+ >>> search_radius=5e-3, max_limit=0, component_only=True)
1366
+ """
1367
+ pinlist = []
1368
+ if not positive_pin:
1369
+ search_radius = 10e-2
1370
+ component_only = True
1371
+ if component_only:
1372
+ references_pins = [
1373
+ pin for pin in list(positive_pin.component.pins.values()) if pin.net_name == reference_net
1374
+ ]
1375
+ if not references_pins:
1376
+ return pinlist
1377
+ else:
1378
+ references_pins = self.get_padstack_instance_by_net_name(reference_net)
1379
+ if not references_pins:
1380
+ return pinlist
1381
+ pinlist = [
1382
+ p
1383
+ for p in references_pins
1384
+ if GeometryOperators.points_distance(positive_pin.position, p.position) <= search_radius
1385
+ ]
1386
+ if max_limit and len(pinlist) > max_limit:
1387
+ pin_dict = {GeometryOperators.points_distance(positive_pin.position, p.position): p for p in pinlist}
1388
+ pinlist = [pin[1] for pin in sorted(pin_dict.items())[:max_limit]]
1389
+ return pinlist