pyedb 0.12.1__py3-none-any.whl → 0.13.dev0__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 (40) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_boundaries.py +1 -1
  3. pyedb/configuration/cfg_common.py +48 -0
  4. pyedb/configuration/cfg_components.py +94 -166
  5. pyedb/configuration/cfg_data.py +12 -7
  6. pyedb/configuration/cfg_general.py +1 -1
  7. pyedb/configuration/cfg_nets.py +1 -1
  8. pyedb/configuration/cfg_operations.py +63 -0
  9. pyedb/configuration/cfg_package_definition.py +128 -0
  10. pyedb/configuration/cfg_padstacks.py +3 -3
  11. pyedb/configuration/cfg_pin_groups.py +1 -1
  12. pyedb/configuration/cfg_ports_sources.py +4 -4
  13. pyedb/configuration/cfg_s_parameter_models.py +1 -1
  14. pyedb/configuration/cfg_setup.py +1 -1
  15. pyedb/configuration/cfg_spice_models.py +1 -1
  16. pyedb/configuration/cfg_stackup.py +169 -0
  17. pyedb/configuration/configuration.py +46 -19
  18. pyedb/dotnet/edb.py +167 -7
  19. pyedb/dotnet/edb_core/cell/hierarchy/model.py +1 -1
  20. pyedb/dotnet/edb_core/{edb_data/connectable.py → cell/layout_obj.py} +1 -1
  21. pyedb/dotnet/edb_core/cell/primitive.py +142 -0
  22. pyedb/dotnet/edb_core/components.py +1 -1
  23. pyedb/dotnet/edb_core/definition/component_def.py +1 -1
  24. pyedb/dotnet/edb_core/definition/component_model.py +1 -1
  25. pyedb/dotnet/edb_core/definition/definition_obj.py +1 -1
  26. pyedb/dotnet/edb_core/definition/package_def.py +2 -1
  27. pyedb/dotnet/edb_core/edb_data/components_data.py +19 -7
  28. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +3 -3
  29. pyedb/dotnet/edb_core/edb_data/primitives_data.py +5 -126
  30. pyedb/dotnet/edb_core/edb_data/terminals.py +2 -2
  31. pyedb/dotnet/edb_core/geometry/polygon_data.py +1 -1
  32. pyedb/dotnet/edb_core/materials.py +2 -1
  33. pyedb/dotnet/edb_core/padstack.py +86 -27
  34. pyedb/generic/general_methods.py +33 -0
  35. pyedb/siwave.py +23 -2
  36. {pyedb-0.12.1.dist-info → pyedb-0.13.dev0.dist-info}/METADATA +2 -2
  37. {pyedb-0.12.1.dist-info → pyedb-0.13.dev0.dist-info}/RECORD +40 -35
  38. /pyedb/dotnet/edb_core/{obj_base.py → utilities/obj_base.py} +0 -0
  39. {pyedb-0.12.1.dist-info → pyedb-0.13.dev0.dist-info}/LICENSE +0 -0
  40. {pyedb-0.12.1.dist-info → pyedb-0.13.dev0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,142 @@
1
+ # Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ from pyedb.dotnet.edb_core.cell.layout_obj import Connectable
24
+
25
+
26
+ class Primitive(Connectable):
27
+ """Manages EDB functionalities for a primitives.
28
+
29
+ It inherits EDB Object properties.
30
+
31
+ Examples
32
+ --------
33
+ >>> from pyedb import Edb
34
+ >>> edb = Edb(myedb, edbversion="2021.2")
35
+ >>> edb_prim = edb.modeler.primitives[0]
36
+ >>> edb_prim.is_void # Class Property
37
+ >>> edb_prim.IsVoid() # EDB Object Property
38
+ """
39
+
40
+ def __init__(self, pedb, edb_object):
41
+ super().__init__(pedb, edb_object)
42
+ self._app = self._pedb
43
+ self._core_stackup = pedb.stackup
44
+ self._core_net = pedb.nets
45
+ self.primitive_object = self._edb_object
46
+
47
+ @property
48
+ def type(self):
49
+ """Return the type of the primitive.
50
+
51
+ Expected output is among ``"Circle"``, ``"Rectangle"``,``"Polygon"``,``"Path"`` or ``"Bondwire"``.
52
+
53
+ Returns
54
+ -------
55
+ str
56
+ """
57
+ try:
58
+ return self._edb_object.GetPrimitiveType().ToString()
59
+ except AttributeError: # pragma: no cover
60
+ return ""
61
+
62
+ @property
63
+ def net_name(self):
64
+ """Get the primitive net name.
65
+
66
+ Returns
67
+ -------
68
+ str
69
+ """
70
+ return self.net.GetName()
71
+
72
+ @net_name.setter
73
+ def net_name(self, name):
74
+ if isinstance(name, str):
75
+ net = self._app.nets.nets[name].net_object
76
+ self.primitive_object.SetNet(net)
77
+ else:
78
+ try:
79
+ self.net = name.name
80
+ except: # pragma: no cover
81
+ self._app.logger.error("Failed to set net name.")
82
+
83
+ @property
84
+ def layer(self):
85
+ """Get the primitive edb layer object."""
86
+ try:
87
+ layer_name = self.primitive_object.GetLayer().GetName()
88
+ return self._pedb.stackup.layers[layer_name]
89
+ except (KeyError, AttributeError): # pragma: no cover
90
+ return None
91
+
92
+ @property
93
+ def layer_name(self):
94
+ """Get the primitive layer name.
95
+
96
+ Returns
97
+ -------
98
+ str
99
+ """
100
+ try:
101
+ return self.layer.name
102
+ except (KeyError, AttributeError): # pragma: no cover
103
+ return None
104
+
105
+ @layer_name.setter
106
+ def layer_name(self, val):
107
+ layer_list = list(self._core_stackup.layers.keys())
108
+ if isinstance(val, str) and val in layer_list:
109
+ layer = self._core_stackup.layers[val]._edb_layer
110
+ if layer:
111
+ self.primitive_object.SetLayer(layer)
112
+ else:
113
+ raise AttributeError("Layer {} not found.".format(val))
114
+ elif isinstance(val, type(self._core_stackup.layers[layer_list[0]])):
115
+ try:
116
+ self.primitive_object.SetLayer(val._edb_layer)
117
+ except:
118
+ raise AttributeError("Failed to assign new layer on primitive.")
119
+ else:
120
+ raise AttributeError("Invalid input value")
121
+
122
+ @property
123
+ def is_void(self):
124
+ """Either if the primitive is a void or not.
125
+
126
+ Returns
127
+ -------
128
+ bool
129
+ """
130
+ try:
131
+ return self._edb_object.IsVoid()
132
+ except AttributeError: # pragma: no cover
133
+ return None
134
+
135
+ def get_connected_objects(self):
136
+ """Get connected objects.
137
+
138
+ Returns
139
+ -------
140
+ list
141
+ """
142
+ return self._pedb.get_connected_objects(self._layout_obj_instance)
@@ -1983,7 +1983,7 @@ class Components(object):
1983
1983
  if not sball_mid_diam:
1984
1984
  sball_mid_diam = sball_diam
1985
1985
 
1986
- if shape == "Cylinder":
1986
+ if shape.lower() == "cylinder":
1987
1987
  sball_shape = self._edb.definition.SolderballShape.Cylinder
1988
1988
  else:
1989
1989
  sball_shape = self._edb.definition.SolderballShape.Spheroid
@@ -23,7 +23,7 @@
23
23
  import os
24
24
 
25
25
  from pyedb.dotnet.edb_core.definition.component_model import NPortComponentModel
26
- from pyedb.dotnet.edb_core.obj_base import ObjBase
26
+ from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
27
27
  from pyedb.generic.general_methods import pyedb_function_handler
28
28
 
29
29
 
@@ -20,7 +20,7 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- from pyedb.dotnet.edb_core.obj_base import ObjBase
23
+ from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
24
24
  from pyedb.generic.general_methods import pyedb_function_handler
25
25
 
26
26
 
@@ -20,7 +20,7 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- from pyedb.dotnet.edb_core.obj_base import ObjBase
23
+ from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
24
24
 
25
25
 
26
26
  class DefinitionObj(ObjBase):
@@ -21,7 +21,7 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  from pyedb.dotnet.edb_core.geometry.polygon_data import PolygonData
24
- from pyedb.dotnet.edb_core.obj_base import ObjBase
24
+ from pyedb.dotnet.edb_core.utilities.obj_base import ObjBase
25
25
  from pyedb.generic.general_methods import pyedb_function_handler
26
26
 
27
27
 
@@ -155,6 +155,7 @@ class PackageDef(ObjBase):
155
155
 
156
156
  @property
157
157
  def heatsink(self):
158
+ """Component heatsink."""
158
159
  from pyedb.dotnet.edb_core.utilities.heatsink import HeatSink
159
160
 
160
161
  flag, edb_object = self._edb_object.GetHeatSink()
@@ -288,10 +288,21 @@ class EDBComponent(object):
288
288
  bool
289
289
  ``True`` if component is active, ``False`` if is disabled..
290
290
  """
291
- return self.component_property.IsEnabled()
291
+ warnings.warn("Use new property :func:`enabled` instead.", DeprecationWarning)
292
+ return self.enabled
292
293
 
293
294
  @is_enabled.setter
294
295
  def is_enabled(self, value):
296
+ warnings.warn("Use new property :func:`enabled` instead.", DeprecationWarning)
297
+ self.enabled = value
298
+
299
+ @property
300
+ def enabled(self):
301
+ """Get or Set the component to active mode."""
302
+ return self.component_property.IsEnabled()
303
+
304
+ @enabled.setter
305
+ def enabled(self, value):
295
306
  cmp_prop = self.component_property.Clone()
296
307
  cmp_prop.SetEnabled(value)
297
308
  self.edbcomponent.SetComponentProperty(cmp_prop)
@@ -773,17 +784,18 @@ class EDBComponent(object):
773
784
  Type of the component. Options are ``"Resistor"``, ``"Inductor"``, ``"Capacitor"``,
774
785
  ``"IC"``, ``"IO"`` and ``"Other"``.
775
786
  """
776
- if new_type == "Resistor":
787
+ new_type = new_type.lower()
788
+ if new_type == "resistor":
777
789
  type_id = self._pedb.definition.ComponentType.Resistor
778
- elif new_type == "Inductor":
790
+ elif new_type == "inductor":
779
791
  type_id = self._pedb.definition.ComponentType.Inductor
780
- elif new_type == "Capacitor":
792
+ elif new_type == "capacitor":
781
793
  type_id = self._pedb.definition.ComponentType.Capacitor
782
- elif new_type == "IC":
794
+ elif new_type == "ic":
783
795
  type_id = self._pedb.definition.ComponentType.IC
784
- elif new_type == "IO":
796
+ elif new_type == "io":
785
797
  type_id = self._pedb.definition.ComponentType.IO
786
- elif new_type == "Other":
798
+ elif new_type == "other":
787
799
  type_id = self._pedb.definition.ComponentType.Other
788
800
  else:
789
801
  return
@@ -26,9 +26,9 @@ import re
26
26
  import warnings
27
27
 
28
28
  from pyedb.dotnet.clr_module import String, _clr
29
+ from pyedb.dotnet.edb_core.cell.primitive import Primitive
29
30
  from pyedb.dotnet.edb_core.dotnet.database import PolygonDataDotNet
30
31
  from pyedb.dotnet.edb_core.edb_data.edbvalue import EdbValue
31
- from pyedb.dotnet.edb_core.edb_data.primitives_data import EDBPrimitivesMain
32
32
  from pyedb.dotnet.edb_core.general import PadGeometryTpe, convert_py_list_to_net_list
33
33
  from pyedb.generic.general_methods import (
34
34
  generate_unique_name,
@@ -1144,7 +1144,7 @@ class EDBPadstack(object):
1144
1144
  return True
1145
1145
 
1146
1146
 
1147
- class EDBPadstackInstance(EDBPrimitivesMain):
1147
+ class EDBPadstackInstance(Primitive):
1148
1148
  """Manages EDB functionalities for a padstack.
1149
1149
 
1150
1150
  Parameters
@@ -1162,7 +1162,7 @@ class EDBPadstackInstance(EDBPrimitivesMain):
1162
1162
  """
1163
1163
 
1164
1164
  def __init__(self, edb_padstackinstance, _pedb):
1165
- super().__init__(edb_padstackinstance, _pedb)
1165
+ super().__init__(_pedb, edb_padstackinstance)
1166
1166
  self._edb_padstackinstance = self._edb_object
1167
1167
  self._bounding_box = []
1168
1168
  self._object_instance = None
@@ -22,7 +22,7 @@
22
22
 
23
23
  import math
24
24
 
25
- from pyedb.dotnet.edb_core.dotnet.database import NetDotNet
25
+ from pyedb.dotnet.edb_core.cell.primitive import Primitive
26
26
  from pyedb.dotnet.edb_core.dotnet.primitive import (
27
27
  BondwireDotNet,
28
28
  CircleDotNet,
@@ -32,7 +32,6 @@ from pyedb.dotnet.edb_core.dotnet.primitive import (
32
32
  RectangleDotNet,
33
33
  TextDotNet,
34
34
  )
35
- from pyedb.dotnet.edb_core.edb_data.connectable import Connectable
36
35
  from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
37
36
  from pyedb.generic.general_methods import pyedb_function_handler
38
37
  from pyedb.modeler.geometry_operators import GeometryOperators
@@ -78,7 +77,7 @@ def cast(raw_primitive, core_app):
78
77
  return None
79
78
 
80
79
 
81
- class EDBPrimitivesMain(Connectable):
80
+ class EDBPrimitives(Primitive):
82
81
  """Manages EDB functionalities for a primitives.
83
82
  It Inherits EDB Object properties.
84
83
 
@@ -92,127 +91,7 @@ class EDBPrimitivesMain(Connectable):
92
91
  """
93
92
 
94
93
  def __init__(self, raw_primitive, core_app):
95
- super().__init__(core_app, raw_primitive)
96
- self._app = self._pedb
97
- self._core_stackup = core_app.stackup
98
- self._core_net = core_app.nets
99
- self.primitive_object = self._edb_object
100
-
101
- @property
102
- def type(self):
103
- """Return the type of the primitive.
104
- Allowed outputs are ``"Circle"``, ``"Rectangle"``,``"Polygon"``,``"Path"`` or ``"Bondwire"``.
105
-
106
- Returns
107
- -------
108
- str
109
- """
110
- try:
111
- return self._edb_object.GetPrimitiveType().ToString()
112
- except AttributeError: # pragma: no cover
113
- return ""
114
-
115
- @property
116
- def net_name(self):
117
- """Get or Set the primitive net name.
118
-
119
- Returns
120
- -------
121
- str
122
- """
123
- return self.net.GetName()
124
-
125
- @net_name.setter
126
- def net_name(self, name):
127
- if isinstance(name, str):
128
- net = self._app.nets.nets[name].net_object
129
- self.primitive_object.SetNet(net)
130
- else:
131
- try:
132
- if isinstance(name, str):
133
- self.net = name
134
- elif isinstance(name, NetDotNet):
135
- self.net = name.name
136
- except: # pragma: no cover
137
- self._app.logger.error("Failed to set net name.")
138
-
139
- @property
140
- def layer(self):
141
- """Get the primitive edb layer object."""
142
- try:
143
- layer_name = self.primitive_object.GetLayer().GetName()
144
- return self._pedb.stackup.layers[layer_name]
145
- except (KeyError, AttributeError): # pragma: no cover
146
- return None
147
-
148
- @property
149
- def layer_name(self):
150
- """Get or Set the primitive layer name.
151
-
152
- Returns
153
- -------
154
- str
155
- """
156
- try:
157
- return self.layer.name
158
- except (KeyError, AttributeError): # pragma: no cover
159
- return None
160
-
161
- @layer_name.setter
162
- def layer_name(self, val):
163
- layer_list = list(self._core_stackup.layers.keys())
164
- if isinstance(val, str) and val in layer_list:
165
- layer = self._core_stackup.layers[val]._edb_layer
166
- if layer:
167
- self.primitive_object.SetLayer(layer)
168
- else:
169
- raise AttributeError("Layer {} not found.".format(val))
170
- elif isinstance(val, type(self._core_stackup.layers[layer_list[0]])):
171
- try:
172
- self.primitive_object.SetLayer(val._edb_layer)
173
- except:
174
- raise AttributeError("Failed to assign new layer on primitive.")
175
- else:
176
- raise AttributeError("Invalid input value")
177
-
178
- @property
179
- def is_void(self):
180
- """Either if the primitive is a void or not.
181
-
182
- Returns
183
- -------
184
- bool
185
- """
186
- try:
187
- return self._edb_object.IsVoid()
188
- except AttributeError: # pragma: no cover
189
- return None
190
-
191
- def get_connected_objects(self):
192
- """Get connected objects.
193
-
194
- Returns
195
- -------
196
- list
197
- """
198
- return self._pedb.get_connected_objects(self._layout_obj_instance)
199
-
200
-
201
- class EDBPrimitives(EDBPrimitivesMain):
202
- """Manages EDB functionalities for a primitives.
203
- It Inherits EDB Object properties.
204
-
205
- Examples
206
- --------
207
- >>> from pyedb import Edb
208
- >>> edb = Edb(myedb, edbversion="2021.2")
209
- >>> edb_prim = edb.modeler.primitives[0]
210
- >>> edb_prim.is_void # Class Property
211
- >>> edb_prim.IsVoid() # EDB Object Property
212
- """
213
-
214
- def __init__(self, raw_primitive, core_app):
215
- EDBPrimitivesMain.__init__(self, raw_primitive, core_app)
94
+ Primitive.__init__(self, core_app, raw_primitive)
216
95
 
217
96
  @pyedb_function_handler()
218
97
  def area(self, include_voids=True):
@@ -1262,13 +1141,13 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
1262
1141
  # return self.add_void(prim)
1263
1142
 
1264
1143
 
1265
- class EdbText(EDBPrimitivesMain, TextDotNet):
1144
+ class EdbText(Primitive, TextDotNet):
1266
1145
  def __init__(self, raw_primitive, core_app):
1267
1146
  EDBPrimitives.__init__(self, raw_primitive, core_app)
1268
1147
  TextDotNet.__init__(self, self._app, raw_primitive)
1269
1148
 
1270
1149
 
1271
- class EdbBondwire(EDBPrimitivesMain, BondwireDotNet):
1150
+ class EdbBondwire(Primitive, BondwireDotNet):
1272
1151
  def __init__(self, raw_primitive, core_app):
1273
1152
  EDBPrimitives.__init__(self, raw_primitive, core_app)
1274
1153
  BondwireDotNet.__init__(self, self._app, raw_primitive)
@@ -22,7 +22,7 @@
22
22
 
23
23
  import re
24
24
 
25
- from pyedb.dotnet.edb_core.edb_data.connectable import Connectable
25
+ from pyedb.dotnet.edb_core.cell.layout_obj import Connectable
26
26
  from pyedb.dotnet.edb_core.edb_data.padstacks_data import EDBPadstackInstance
27
27
  from pyedb.dotnet.edb_core.edb_data.primitives_data import cast
28
28
  from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
@@ -542,7 +542,7 @@ class PadstackInstanceTerminal(Terminal):
542
542
 
543
543
  terminal = self._edb.cell.terminal.PadstackInstanceTerminal.Create(
544
544
  self._pedb.active_layout,
545
- self.net.net_object,
545
+ padstack_instance.net.net_object,
546
546
  name,
547
547
  padstack_instance._edb_object,
548
548
  layer_obj._edb_layer,
@@ -21,7 +21,7 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  from pyedb.dotnet.edb_core.geometry.point_data import PointData
24
- from pyedb.dotnet.edb_core.obj_base import BBox
24
+ from pyedb.dotnet.edb_core.utilities.obj_base import BBox
25
25
  from pyedb.generic.general_methods import pyedb_function_handler
26
26
 
27
27
 
@@ -513,7 +513,8 @@ class Materials(object):
513
513
  if name in curr_materials:
514
514
  raise ValueError(f"Material {name} already exists in material library.")
515
515
  elif name.lower() in (material.lower() for material in curr_materials):
516
- raise ValueError(f"Material names are case-insensitive and {name.lower()} already exists.")
516
+ m = {material.lower(): material for material in curr_materials}[name.lower()]
517
+ raise ValueError(f"Material names are case-insensitive and '{name}' already exists as '{m}'.")
517
518
 
518
519
  material_def = self.__edb_definition.MaterialDef.Create(self.__edb.active_db, name)
519
520
  material = Material(self.__edb, material_def)
@@ -29,6 +29,7 @@ import warnings
29
29
  import rtree
30
30
 
31
31
  from pyedb.dotnet.clr_module import Array
32
+ from pyedb.dotnet.edb_core.dotnet.database import PolygonDataDotNet
32
33
  from pyedb.dotnet.edb_core.edb_data.padstacks_data import (
33
34
  EDBPadstack,
34
35
  EDBPadstackInstance,
@@ -868,6 +869,9 @@ class EdbPadstacks(object):
868
869
  pad_offset_x="0.0",
869
870
  pad_offset_y="0.0",
870
871
  pad_rotation="0.0",
872
+ pad_polygon=None,
873
+ antipad_polygon=None,
874
+ polygon_hole=None,
871
875
  start_layer=None,
872
876
  stop_layer=None,
873
877
  add_default_layer=False,
@@ -888,7 +892,7 @@ class EdbPadstacks(object):
888
892
  antipaddiam : str, optional
889
893
  Diameter of the antipad with units. The default is ``"600um"``.
890
894
  pad_shape : str, optional
891
- Shape of the pad. The default is ``"Circle``. Options are ``"Circle"`` and ``"Rectangle"``.
895
+ Shape of the pad. The default is ``"Circle``. Options are ``"Circle"``, ``"Rectangle"`` and ``"Polygon"``.
892
896
  antipad_shape : str, optional
893
897
  Shape of the antipad. The default is ``"Circle"``. Options are ``"Circle"`` ``"Rectangle"`` and
894
898
  ``"Bullet"``.
@@ -934,17 +938,34 @@ class EdbPadstacks(object):
934
938
  holediam = self._get_edb_value(holediam)
935
939
  paddiam = self._get_edb_value(paddiam)
936
940
  antipaddiam = self._get_edb_value(antipaddiam)
937
-
941
+ layers = list(self._pedb.stackup.signal_layers.keys())[:]
942
+ value0 = self._get_edb_value("0.0")
938
943
  if not padstackname:
939
944
  padstackname = generate_unique_name("VIA")
940
945
  # assert not self.isreadonly, "Write Functions are not available within AEDT"
941
946
  padstackData = self._edb.definition.PadstackDefData.Create()
942
- if has_hole:
947
+ if has_hole and not polygon_hole:
943
948
  ptype = self._edb.definition.PadGeometryType.Circle
949
+ hole_param = Array[type(holediam)]([holediam])
950
+ padstackData.SetHoleParameters(ptype, hole_param, value0, value0, value0)
951
+ padstackData.SetHolePlatingPercentage(self._get_edb_value(20.0))
952
+ elif polygon_hole:
953
+ if isinstance(polygon_hole, list):
954
+ _poly = self._pedb.modeler.create_polygon(polygon_hole, layers[0], net_name="dummy")
955
+ if not _poly.is_null:
956
+ hole_param = _poly.polygon_data
957
+ _poly.delete()
958
+ else:
959
+ return False
960
+ elif isinstance(polygon_hole, PolygonDataDotNet):
961
+ hole_param = polygon_hole
962
+ else:
963
+ return False
964
+ padstackData.SetPolygonalHoleParameters(hole_param, value0, value0, value0)
965
+ padstackData.SetHolePlatingPercentage(self._get_edb_value(20.0))
944
966
  else:
945
967
  ptype = self._edb.definition.PadGeometryType.NoGeometry
946
- holparam = Array[type(holediam)]([holediam])
947
- value0 = self._get_edb_value("0.0")
968
+
948
969
  x_size = self._get_edb_value(x_size)
949
970
  y_size = self._get_edb_value(y_size)
950
971
  corner_radius = self._get_edb_value(corner_radius)
@@ -957,8 +978,7 @@ class EdbPadstacks(object):
957
978
  pad_rotation = self._get_edb_value(pad_rotation)
958
979
  anti_pad_x_size = self._get_edb_value(anti_pad_x_size)
959
980
  anti_pad_y_size = self._get_edb_value(anti_pad_y_size)
960
- padstackData.SetHoleParameters(ptype, holparam, value0, value0, value0)
961
- padstackData.SetHolePlatingPercentage(self._get_edb_value(20.0))
981
+
962
982
  if hole_range == "through": # pragma no cover
963
983
  padstackData.SetHoleRange(self._edb.definition.PadstackHoleRange.Through)
964
984
  elif hole_range == "begin_on_upper_pad": # pragma no cover
@@ -970,7 +990,7 @@ class EdbPadstacks(object):
970
990
  else: # pragma no cover
971
991
  self._logger.error("Unknown padstack hole range")
972
992
  padstackData.SetMaterial("copper")
973
- layers = list(self._pedb.stackup.signal_layers.keys())[:]
993
+
974
994
  if start_layer and start_layer in layers: # pragma no cover
975
995
  layers = layers[layers.index(start_layer) :]
976
996
  if stop_layer and stop_layer in layers: # pragma no cover
@@ -981,37 +1001,76 @@ class EdbPadstacks(object):
981
1001
  elif pad_shape == "Rectangle": # pragma no cover
982
1002
  pad_array = Array[type(x_size)]([x_size, y_size])
983
1003
  pad_shape = self._edb.definition.PadGeometryType.Rectangle
1004
+ elif pad_shape == "Polygon":
1005
+ if isinstance(pad_polygon, list):
1006
+ _poly = self._pedb.modeler.create_polygon(pad_polygon, layers[0], net_name="dummy")
1007
+ if not _poly.is_null:
1008
+ pad_array = _poly.polygon_data
1009
+ _poly.delete()
1010
+ else:
1011
+ return False
1012
+ elif isinstance(pad_polygon, PolygonDataDotNet):
1013
+ pad_array = pad_polygon
984
1014
  if antipad_shape == "Bullet": # pragma no cover
985
1015
  antipad_array = Array[type(x_size)]([x_size, y_size, corner_radius])
986
1016
  antipad_shape = self._edb.definition.PadGeometryType.Bullet
987
1017
  elif antipad_shape == "Rectangle": # pragma no cover
988
1018
  antipad_array = Array[type(anti_pad_x_size)]([anti_pad_x_size, anti_pad_y_size])
989
1019
  antipad_shape = self._edb.definition.PadGeometryType.Rectangle
1020
+ elif antipad_shape == "Polygon":
1021
+ if isinstance(antipad_polygon, list):
1022
+ _poly = self._pedb.modeler.create_polygon(antipad_polygon, layers[0], net_name="dummy")
1023
+ if not _poly.is_null:
1024
+ antipad_array = _poly.polygon_data
1025
+ _poly.delete()
1026
+ else:
1027
+ return False
1028
+ elif isinstance(antipad_polygon, PolygonDataDotNet):
1029
+ antipad_array = antipad_polygon
990
1030
  else: # pragma no cover
991
1031
  antipad_array = Array[type(antipaddiam)]([antipaddiam])
992
1032
  antipad_shape = self._edb.definition.PadGeometryType.Circle
993
1033
  if add_default_layer: # pragma no cover
994
1034
  layers = layers + ["Default"]
995
- for layer in layers:
996
- padstackData.SetPadParameters(
997
- layer,
998
- self._edb.definition.PadType.RegularPad,
999
- pad_shape,
1000
- pad_array,
1001
- pad_offset_x,
1002
- pad_offset_y,
1003
- pad_rotation,
1004
- )
1035
+ if antipad_shape == "Polygon" and pad_shape == "Polygon":
1036
+ for layer in layers:
1037
+ padstackData.SetPolygonalPadParameters(
1038
+ layer,
1039
+ self._edb.definition.PadType.RegularPad,
1040
+ pad_array.edb_api,
1041
+ pad_offset_x,
1042
+ pad_offset_y,
1043
+ pad_rotation,
1044
+ )
1045
+ padstackData.SetPolygonalPadParameters(
1046
+ layer,
1047
+ self._edb.definition.PadType.AntiPad,
1048
+ antipad_array.edb_api,
1049
+ pad_offset_x,
1050
+ pad_offset_y,
1051
+ pad_rotation,
1052
+ )
1053
+ else:
1054
+ for layer in layers:
1055
+ padstackData.SetPadParameters(
1056
+ layer,
1057
+ self._edb.definition.PadType.RegularPad,
1058
+ pad_shape,
1059
+ pad_array,
1060
+ pad_offset_x,
1061
+ pad_offset_y,
1062
+ pad_rotation,
1063
+ )
1005
1064
 
1006
- padstackData.SetPadParameters(
1007
- layer,
1008
- self._edb.definition.PadType.AntiPad,
1009
- antipad_shape,
1010
- antipad_array,
1011
- offset_x,
1012
- offset_y,
1013
- rotation,
1014
- )
1065
+ padstackData.SetPadParameters(
1066
+ layer,
1067
+ self._edb.definition.PadType.AntiPad,
1068
+ antipad_shape,
1069
+ antipad_array,
1070
+ offset_x,
1071
+ offset_y,
1072
+ rotation,
1073
+ )
1015
1074
 
1016
1075
  padstackDefinition = self._edb.definition.PadstackDef.Create(self.db, padstackname)
1017
1076
  padstackDefinition.SetData(padstackData)