pyedb 0.36.0__py3-none-any.whl → 0.38.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_common.py +1 -1
- pyedb/configuration/cfg_components.py +228 -200
- pyedb/configuration/cfg_data.py +3 -1
- pyedb/configuration/cfg_modeler.py +6 -6
- pyedb/configuration/cfg_padstacks.py +345 -289
- pyedb/configuration/cfg_ports_sources.py +191 -42
- pyedb/configuration/configuration.py +5 -2
- pyedb/dotnet/edb.py +1 -1
- pyedb/dotnet/edb_core/cell/layout.py +24 -8
- pyedb/dotnet/edb_core/edb_data/nets_data.py +1 -1
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +62 -26
- pyedb/dotnet/edb_core/geometry/polygon_data.py +5 -0
- pyedb/dotnet/edb_core/modeler.py +1 -2
- pyedb/dotnet/edb_core/padstack.py +2 -1
- pyedb/dotnet/edb_core/sim_setup_data/data/settings.py +15 -0
- pyedb/dotnet/edb_core/sim_setup_data/data/sweep_data.py +3 -3
- pyedb/dotnet/edb_core/utilities/simulation_setup.py +1 -0
- pyedb/extensions/pre_layout_design_toolkit/via_design.py +1151 -0
- pyedb/ipc2581/ecad/cad_data/step.py +1 -1
- {pyedb-0.36.0.dist-info → pyedb-0.38.0.dist-info}/METADATA +5 -5
- {pyedb-0.36.0.dist-info → pyedb-0.38.0.dist-info}/RECORD +24 -23
- {pyedb-0.36.0.dist-info → pyedb-0.38.0.dist-info}/LICENSE +0 -0
- {pyedb-0.36.0.dist-info → pyedb-0.38.0.dist-info}/WHEEL +0 -0
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
|
+
import os
|
|
22
23
|
|
|
23
24
|
from pyedb.configuration.cfg_common import CfgBase
|
|
24
25
|
from pyedb.dotnet.edb_core.general import (
|
|
@@ -32,20 +33,20 @@ class CfgPadstacks:
|
|
|
32
33
|
"""Padstack data class."""
|
|
33
34
|
|
|
34
35
|
def __init__(self, pedb, padstack_dict=None):
|
|
35
|
-
self.
|
|
36
|
+
self.pedb = pedb
|
|
36
37
|
self.definitions = []
|
|
37
38
|
self.instances = []
|
|
38
39
|
|
|
39
40
|
if padstack_dict:
|
|
40
|
-
padstack_defs_layout = self.
|
|
41
|
+
padstack_defs_layout = self.pedb.padstacks.definitions
|
|
41
42
|
for pdef in padstack_dict.get("definitions", []):
|
|
42
43
|
obj = padstack_defs_layout[pdef["name"]]
|
|
43
|
-
self.definitions.append(CfgPadstackDefinition(self.
|
|
44
|
+
self.definitions.append(CfgPadstackDefinition(self.pedb, obj, **pdef))
|
|
44
45
|
|
|
45
|
-
inst_from_layout = self.
|
|
46
|
+
inst_from_layout = self.pedb.padstacks.instances_by_name
|
|
46
47
|
for inst in padstack_dict.get("instances", []):
|
|
47
48
|
obj = inst_from_layout[inst["name"]]
|
|
48
|
-
self.instances.append(CfgPadstackInstance(self.
|
|
49
|
+
self.instances.append(CfgPadstackInstance(self.pedb, obj, **inst))
|
|
49
50
|
|
|
50
51
|
def clean(self):
|
|
51
52
|
self.definitions = []
|
|
@@ -55,43 +56,298 @@ class CfgPadstacks:
|
|
|
55
56
|
"""Apply padstack definition and instances on layout."""
|
|
56
57
|
if self.definitions:
|
|
57
58
|
for pdef in self.definitions:
|
|
58
|
-
pdef.set_parameters_to_edb()
|
|
59
|
+
pdef.api.set_parameters_to_edb()
|
|
59
60
|
if self.instances:
|
|
60
61
|
for inst in self.instances:
|
|
61
|
-
inst.set_parameters_to_edb()
|
|
62
|
+
inst.api.set_parameters_to_edb()
|
|
62
63
|
|
|
63
64
|
def retrieve_parameters_from_edb(self):
|
|
64
65
|
self.clean()
|
|
65
|
-
for name, obj in self.
|
|
66
|
+
for name, obj in self.pedb.padstacks.definitions.items():
|
|
66
67
|
if name.lower() == "symbol":
|
|
67
68
|
continue
|
|
68
|
-
pdef = CfgPadstackDefinition(self.
|
|
69
|
-
pdef.retrieve_parameters_from_edb()
|
|
69
|
+
pdef = CfgPadstackDefinition(self.pedb, obj)
|
|
70
|
+
pdef.api.retrieve_parameters_from_edb()
|
|
70
71
|
self.definitions.append(pdef)
|
|
71
72
|
|
|
72
|
-
for obj in self.
|
|
73
|
-
inst = CfgPadstackInstance(self.
|
|
74
|
-
inst.retrieve_parameters_from_edb()
|
|
73
|
+
for obj in self.pedb.layout.padstack_instances:
|
|
74
|
+
inst = CfgPadstackInstance(self.pedb, obj)
|
|
75
|
+
inst.api.retrieve_parameters_from_edb()
|
|
75
76
|
self.instances.append(inst)
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
class CfgPadstackDefinition(CfgBase):
|
|
79
80
|
"""Padstack definition data class."""
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
class Common:
|
|
83
|
+
PAD_SHAPE_PARAMETERS = {
|
|
84
|
+
"circle": ["diameter"],
|
|
85
|
+
"square": ["size"],
|
|
86
|
+
"rectangle": ["x_size", "y_size"],
|
|
87
|
+
"oval": ["x_size", "y_size", "corner_radius"],
|
|
88
|
+
"bullet": ["x_size", "y_size", "corner_radius"],
|
|
89
|
+
"round45": ["inner", "channel_width", "isolation_gap"],
|
|
90
|
+
"round90": ["inner", "channel_width", "isolation_gap"],
|
|
91
|
+
"no_geometry": [],
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def pyedb_obj(self):
|
|
96
|
+
return self.parent.pyedb_obj
|
|
97
|
+
|
|
98
|
+
def __init__(self, parent):
|
|
99
|
+
self.parent = parent
|
|
100
|
+
self.pedb = parent.pedb
|
|
101
|
+
|
|
102
|
+
definition = self.pedb._edb.Definition
|
|
103
|
+
self._solder_shape_type = {
|
|
104
|
+
"no_solder_ball": definition.SolderballShape.NoSolderball,
|
|
105
|
+
"cylinder": definition.SolderballShape.Cylinder,
|
|
106
|
+
"spheroid": definition.SolderballShape.Spheroid,
|
|
107
|
+
}
|
|
108
|
+
self._solder_placement = {
|
|
109
|
+
"above_padstack": definition.SolderballPlacement.AbovePadstack,
|
|
110
|
+
"below_padstack": definition.SolderballPlacement.BelowPadstack,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
def set_parameters_to_edb(self):
|
|
114
|
+
if self.parent.hole_parameters:
|
|
115
|
+
self._set_hole_parameters_to_edb(self.parent.hole_parameters)
|
|
116
|
+
if self.parent.hole_range:
|
|
117
|
+
self.pyedb_obj.hole_range = self.parent.hole_range
|
|
118
|
+
if self.parent.hole_plating_thickness:
|
|
119
|
+
self.pyedb_obj.hole_plating_thickness = self.parent.hole_plating_thickness
|
|
120
|
+
if self.parent.material:
|
|
121
|
+
self.pyedb_obj.material = self.parent.material
|
|
122
|
+
if self.parent.pad_parameters:
|
|
123
|
+
self._set_pad_parameters_to_edb(self.parent.pad_parameters)
|
|
124
|
+
if self.parent.solder_ball_parameters:
|
|
125
|
+
self._set_solder_parameters_to_edb(self.parent.solder_ball_parameters)
|
|
126
|
+
|
|
127
|
+
def retrieve_parameters_from_edb(self):
|
|
128
|
+
self.parent.name = self.pyedb_obj.name
|
|
129
|
+
self.parent.hole_plating_thickness = self.pyedb_obj.hole_plating_thickness
|
|
130
|
+
self.parent.material = self.pyedb_obj.material
|
|
131
|
+
self.parent.hole_range = self.pyedb_obj.hole_range
|
|
132
|
+
self.parent.pad_parameters = self._get_pad_parameters_from_edb()
|
|
133
|
+
self.parent.hole_parameters = self._get_hole_parameters_from_edb()
|
|
134
|
+
self.parent.solder_ball_parameters = self._get_solder_parameters_from_edb()
|
|
135
|
+
|
|
136
|
+
def _set_solder_parameters_to_edb(self, parameters):
|
|
137
|
+
pdef_data = self.pyedb_obj._padstack_def_data
|
|
138
|
+
|
|
139
|
+
shape = parameters.get("shape", "no_solder_ball")
|
|
140
|
+
diameter = parameters.get("diameter", "0.4mm")
|
|
141
|
+
mid_diameter = parameters.get("mid_diameter", diameter)
|
|
142
|
+
placement = parameters.get("placement", "above_padstack")
|
|
143
|
+
material = parameters.get("material", None)
|
|
144
|
+
|
|
145
|
+
pdef_data.SetSolderBallShape(self._solder_shape_type[shape])
|
|
146
|
+
if not shape == "no_solder_ball":
|
|
147
|
+
pdef_data.SetSolderBallParameter(self.pedb.edb_value(diameter), self.pedb.edb_value(mid_diameter))
|
|
148
|
+
pdef_data.SetSolderBallPlacement(self._solder_placement[placement])
|
|
149
|
+
|
|
150
|
+
if material:
|
|
151
|
+
pdef_data.SetSolderBallMaterial(material)
|
|
152
|
+
self.pyedb_obj._padstack_def_data = pdef_data
|
|
153
|
+
|
|
154
|
+
def _get_solder_parameters_from_edb(self):
|
|
155
|
+
pdef_data = self.parent.pyedb_obj._padstack_def_data
|
|
156
|
+
shape = pdef_data.GetSolderBallShape()
|
|
157
|
+
_, diameter, mid_diameter = pdef_data.GetSolderBallParameterValue()
|
|
158
|
+
placement = pdef_data.GetSolderBallPlacement()
|
|
159
|
+
material = pdef_data.GetSolderBallMaterial()
|
|
160
|
+
|
|
161
|
+
parameters = {
|
|
162
|
+
"shape": [i for i, j in self._solder_shape_type.items() if j == shape][0],
|
|
163
|
+
"diameter": self.pedb.edb_value(diameter).ToString(),
|
|
164
|
+
"mid_diameter": self.pedb.edb_value(mid_diameter).ToString(),
|
|
165
|
+
"placement": [i for i, j in self._solder_placement.items() if j == placement][0],
|
|
166
|
+
"material": material,
|
|
167
|
+
}
|
|
168
|
+
return parameters
|
|
169
|
+
|
|
170
|
+
def _get_pad_parameters_from_edb(self):
|
|
171
|
+
"""Pad parameters.
|
|
172
|
+
|
|
173
|
+
Returns
|
|
174
|
+
-------
|
|
175
|
+
dict
|
|
176
|
+
params = {
|
|
177
|
+
'regular_pad': [
|
|
178
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0',
|
|
179
|
+
'diameter': '0.5mm'}
|
|
180
|
+
],
|
|
181
|
+
'anti_pad': [
|
|
182
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
183
|
+
'diameter': '1mm'}
|
|
184
|
+
],
|
|
185
|
+
'thermal_pad': [
|
|
186
|
+
{'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
187
|
+
'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'},
|
|
188
|
+
],
|
|
189
|
+
'hole': [
|
|
190
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
191
|
+
'diameter': '0.1499997mm'},
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
"""
|
|
195
|
+
pdef_data = self.pyedb_obj._padstack_def_data
|
|
196
|
+
pad_type_list = [
|
|
197
|
+
self.pedb._edb.Definition.PadType.RegularPad,
|
|
198
|
+
self.pedb._edb.Definition.PadType.AntiPad,
|
|
199
|
+
self.pedb._edb.Definition.PadType.ThermalPad,
|
|
200
|
+
# self._ppadstack._pedb._edb.Definition.PadType.Hole,
|
|
201
|
+
# This property doesn't appear in UI. It is unclear what it is used for.
|
|
202
|
+
# Suppressing this property for now.
|
|
203
|
+
]
|
|
204
|
+
data = {}
|
|
205
|
+
for pad_type in pad_type_list:
|
|
206
|
+
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
207
|
+
temp_list = []
|
|
208
|
+
for lyr_name in list(pdef_data.GetLayerNames()):
|
|
209
|
+
result = pdef_data.GetPadParametersValue(lyr_name, pad_type)
|
|
210
|
+
_, pad_shape, params, offset_x, offset_y, rotation = result
|
|
211
|
+
pad_shape = pascal_to_snake(pad_shape.ToString())
|
|
212
|
+
|
|
213
|
+
pad_params = {}
|
|
214
|
+
pad_params["layer_name"] = lyr_name
|
|
215
|
+
pad_params["shape"] = pad_shape
|
|
216
|
+
pad_params["offset_x"] = offset_x.ToString()
|
|
217
|
+
pad_params["offset_y"] = offset_y.ToString()
|
|
218
|
+
pad_params["rotation"] = rotation.ToString()
|
|
219
|
+
|
|
220
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[pad_shape]):
|
|
221
|
+
pad_params[i] = params[idx].ToString()
|
|
222
|
+
temp_list.append(pad_params)
|
|
223
|
+
data[pad_type_name] = temp_list
|
|
224
|
+
return data
|
|
225
|
+
|
|
226
|
+
def _set_pad_parameters_to_edb(self, param):
|
|
227
|
+
pdef_data = self.pyedb_obj._padstack_def_data
|
|
228
|
+
|
|
229
|
+
pad_type_list = [
|
|
230
|
+
self.pedb._edb.Definition.PadType.RegularPad,
|
|
231
|
+
self.pedb._edb.Definition.PadType.AntiPad,
|
|
232
|
+
self.pedb._edb.Definition.PadType.ThermalPad,
|
|
233
|
+
self.pedb._edb.Definition.PadType.Hole,
|
|
234
|
+
]
|
|
235
|
+
for pad_type in pad_type_list:
|
|
236
|
+
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
237
|
+
rpp = param.get(pad_type_name, [])
|
|
238
|
+
for idx, layer_data in enumerate(rpp):
|
|
239
|
+
# Get geometry type from kwargs
|
|
240
|
+
p = layer_data.get("shape")
|
|
241
|
+
temp_param = []
|
|
242
|
+
|
|
243
|
+
# Handle Circle geometry type
|
|
244
|
+
if p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Circle.ToString()):
|
|
245
|
+
temp_param.append(layer_data["diameter"])
|
|
246
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Circle
|
|
247
|
+
|
|
248
|
+
# Handle Square geometry type
|
|
249
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Square.ToString()):
|
|
250
|
+
temp_param.append(layer_data["size"])
|
|
251
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Square
|
|
252
|
+
|
|
253
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Rectangle.ToString()):
|
|
254
|
+
temp_param.append(layer_data["x_size"])
|
|
255
|
+
temp_param.append(layer_data["y_size"])
|
|
256
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Rectangle
|
|
257
|
+
|
|
258
|
+
# Handle Oval geometry type
|
|
259
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Oval.ToString()):
|
|
260
|
+
temp_param.append(layer_data["x_size"])
|
|
261
|
+
temp_param.append(layer_data["y_size"])
|
|
262
|
+
temp_param.append(layer_data["corner_radius"])
|
|
263
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Oval
|
|
264
|
+
|
|
265
|
+
# Handle Bullet geometry type
|
|
266
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Bullet.ToString()):
|
|
267
|
+
temp_param.append(layer_data["x_size"])
|
|
268
|
+
temp_param.append(layer_data["y_size"])
|
|
269
|
+
temp_param.append(layer_data["corner_radius"])
|
|
270
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Bullet
|
|
271
|
+
|
|
272
|
+
# Handle Round45 geometry type
|
|
273
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Round45.ToString()):
|
|
274
|
+
temp_param.append(layer_data["inner"])
|
|
275
|
+
temp_param.append(layer_data["channel_width"])
|
|
276
|
+
temp_param.append(layer_data["isolation_gap"])
|
|
277
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Round45
|
|
278
|
+
|
|
279
|
+
# Handle Round90 geometry type
|
|
280
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.Round90.ToString()):
|
|
281
|
+
temp_param.append(layer_data["inner"])
|
|
282
|
+
temp_param.append(layer_data["channel_width"])
|
|
283
|
+
temp_param.append(layer_data["isolation_gap"])
|
|
284
|
+
pad_shape = self.pedb._edb.Definition.PadGeometryType.Round90
|
|
285
|
+
elif p == pascal_to_snake(self.pedb._edb.Definition.PadGeometryType.NoGeometry.ToString()):
|
|
286
|
+
continue
|
|
287
|
+
|
|
288
|
+
# Set pad parameters for the current layer
|
|
289
|
+
pdef_data.SetPadParameters(
|
|
290
|
+
layer_data["layer_name"],
|
|
291
|
+
pad_type,
|
|
292
|
+
pad_shape,
|
|
293
|
+
convert_py_list_to_net_list([self.pedb.edb_value(i) for i in temp_param]),
|
|
294
|
+
self.pedb.edb_value(layer_data.get("offset_x", 0)),
|
|
295
|
+
self.pedb.edb_value(layer_data.get("offset_y", 0)),
|
|
296
|
+
self.pedb.edb_value(layer_data.get("rotation", 0)),
|
|
297
|
+
)
|
|
298
|
+
self.pyedb_obj._padstack_def_data = pdef_data
|
|
299
|
+
|
|
300
|
+
def _get_hole_parameters_from_edb(self):
|
|
301
|
+
pdef_data = self.pyedb_obj._padstack_def_data
|
|
302
|
+
_, hole_shape, params, offset_x, offset_y, rotation = pdef_data.GetHoleParametersValue()
|
|
303
|
+
hole_shape = pascal_to_snake(hole_shape.ToString())
|
|
304
|
+
|
|
305
|
+
hole_params = {}
|
|
306
|
+
hole_params["shape"] = hole_shape
|
|
307
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[hole_shape]):
|
|
308
|
+
hole_params[i] = params[idx].ToString()
|
|
309
|
+
hole_params["offset_x"] = offset_x.ToString()
|
|
310
|
+
hole_params["offset_y"] = offset_y.ToString()
|
|
311
|
+
hole_params["rotation"] = rotation.ToString()
|
|
312
|
+
return hole_params
|
|
313
|
+
|
|
314
|
+
def _set_hole_parameters_to_edb(self, params):
|
|
315
|
+
original_params = self.parent.hole_parameters
|
|
316
|
+
pdef_data = self.pyedb_obj._padstack_def_data
|
|
317
|
+
|
|
318
|
+
temp_param = []
|
|
319
|
+
shape = params["shape"]
|
|
320
|
+
if shape == "no_geometry":
|
|
321
|
+
return # .net api doesn't tell how to set no_geometry shape.
|
|
322
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[shape]):
|
|
323
|
+
temp_param.append(params[i])
|
|
324
|
+
pedb_shape = getattr(self.pedb._edb.Definition.PadGeometryType, snake_to_pascal(shape))
|
|
325
|
+
|
|
326
|
+
pdef_data.SetHoleParameters(
|
|
327
|
+
pedb_shape,
|
|
328
|
+
convert_py_list_to_net_list([self.pedb.edb_value(i) for i in temp_param]),
|
|
329
|
+
self.pedb.edb_value(params.get("offset_x", original_params.get("offset_x", 0))),
|
|
330
|
+
self.pedb.edb_value(params.get("offset_y", original_params.get("offset_y", 0))),
|
|
331
|
+
self.pedb.edb_value(params.get("rotation", original_params.get("rotation", 0))),
|
|
332
|
+
)
|
|
333
|
+
self.pyedb_obj._padstack_def_data = pdef_data
|
|
334
|
+
|
|
335
|
+
class Grpc(Common):
|
|
336
|
+
def __init__(self, parent):
|
|
337
|
+
super().__init__(parent)
|
|
338
|
+
|
|
339
|
+
class DotNet(Grpc):
|
|
340
|
+
def __init__(self, parent):
|
|
341
|
+
super().__init__(parent)
|
|
91
342
|
|
|
92
343
|
def __init__(self, pedb, pedb_object, **kwargs):
|
|
93
|
-
self.
|
|
94
|
-
self.
|
|
344
|
+
self.pedb = pedb
|
|
345
|
+
self.pyedb_obj = pedb_object
|
|
346
|
+
if os.environ["PYEDB_USE_DOTNET"] == "0":
|
|
347
|
+
self.api = self.Grpc(self)
|
|
348
|
+
else:
|
|
349
|
+
self.api = self.DotNet(self)
|
|
350
|
+
|
|
95
351
|
self.name = kwargs.get("name", None)
|
|
96
352
|
self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None)
|
|
97
353
|
self.material = kwargs.get("hole_material", None)
|
|
@@ -100,244 +356,76 @@ class CfgPadstackDefinition(CfgBase):
|
|
|
100
356
|
self.hole_parameters = kwargs.get("hole_parameters", None)
|
|
101
357
|
self.solder_ball_parameters = kwargs.get("solder_ball_parameters", None)
|
|
102
358
|
|
|
103
|
-
self._solder_shape_type = {
|
|
104
|
-
"no_solder_ball": self._pedb._edb.Definition.SolderballShape.NoSolderball,
|
|
105
|
-
"cylinder": self._pedb._edb.Definition.SolderballShape.Cylinder,
|
|
106
|
-
"spheroid": self._pedb._edb.Definition.SolderballShape.Spheroid,
|
|
107
|
-
}
|
|
108
|
-
self._solder_placement = {
|
|
109
|
-
"above_padstack": self._pedb._edb.Definition.SolderballPlacement.AbovePadstack,
|
|
110
|
-
"below_padstack": self._pedb._edb.Definition.SolderballPlacement.BelowPadstack,
|
|
111
|
-
}
|
|
112
359
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
self._set_hole_parameters_to_edb(self.hole_parameters)
|
|
116
|
-
if self.hole_range:
|
|
117
|
-
self._pyedb_obj.hole_range = self.hole_range
|
|
118
|
-
if self.hole_plating_thickness:
|
|
119
|
-
self._pyedb_obj.hole_plating_thickness = self.hole_plating_thickness
|
|
120
|
-
if self.material:
|
|
121
|
-
self._pyedb_obj.material = self.material
|
|
122
|
-
if self.pad_parameters:
|
|
123
|
-
self._set_pad_parameters_to_edb(self.pad_parameters)
|
|
124
|
-
if self.solder_ball_parameters:
|
|
125
|
-
self._set_solder_parameters_to_edb(self.solder_ball_parameters)
|
|
360
|
+
class CfgPadstackInstance(CfgBase):
|
|
361
|
+
"""Instance data class."""
|
|
126
362
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
self
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if material:
|
|
151
|
-
pdef_data.SetSolderBallMaterial(material)
|
|
152
|
-
self._pyedb_obj._padstack_def_data = pdef_data
|
|
153
|
-
|
|
154
|
-
def _get_solder_parameters_from_edb(self):
|
|
155
|
-
pdef_data = self._pyedb_obj._padstack_def_data
|
|
156
|
-
shape = pdef_data.GetSolderBallShape()
|
|
157
|
-
_, diameter, mid_diameter = pdef_data.GetSolderBallParameterValue()
|
|
158
|
-
placement = pdef_data.GetSolderBallPlacement()
|
|
159
|
-
material = pdef_data.GetSolderBallMaterial()
|
|
160
|
-
|
|
161
|
-
parameters = {
|
|
162
|
-
"shape": [i for i, j in self._solder_shape_type.items() if j == shape][0],
|
|
163
|
-
"diameter": self._pedb.edb_value(diameter).ToString(),
|
|
164
|
-
"mid_diameter": self._pedb.edb_value(mid_diameter).ToString(),
|
|
165
|
-
"placement": [i for i, j in self._solder_placement.items() if j == placement][0],
|
|
166
|
-
"material": material,
|
|
167
|
-
}
|
|
168
|
-
return parameters
|
|
169
|
-
|
|
170
|
-
def _get_pad_parameters_from_edb(self):
|
|
171
|
-
"""Pad parameters.
|
|
172
|
-
|
|
173
|
-
Returns
|
|
174
|
-
-------
|
|
175
|
-
dict
|
|
176
|
-
params = {
|
|
177
|
-
'regular_pad': [
|
|
178
|
-
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0',
|
|
179
|
-
'diameter': '0.5mm'}
|
|
180
|
-
],
|
|
181
|
-
'anti_pad': [
|
|
182
|
-
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
183
|
-
'diameter': '1mm'}
|
|
184
|
-
],
|
|
185
|
-
'thermal_pad': [
|
|
186
|
-
{'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
187
|
-
'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'},
|
|
188
|
-
],
|
|
189
|
-
'hole': [
|
|
190
|
-
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
191
|
-
'diameter': '0.1499997mm'},
|
|
192
|
-
]
|
|
193
|
-
}
|
|
194
|
-
"""
|
|
195
|
-
pdef_data = self._pyedb_obj._padstack_def_data
|
|
196
|
-
pad_type_list = [
|
|
197
|
-
self._pedb._edb.Definition.PadType.RegularPad,
|
|
198
|
-
self._pedb._edb.Definition.PadType.AntiPad,
|
|
199
|
-
self._pedb._edb.Definition.PadType.ThermalPad,
|
|
200
|
-
# self._ppadstack._pedb._edb.Definition.PadType.Hole,
|
|
201
|
-
# This property doesn't appear in UI. It is unclear what it is used for. Suppressing this property for now.
|
|
202
|
-
]
|
|
203
|
-
data = {}
|
|
204
|
-
for pad_type in pad_type_list:
|
|
205
|
-
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
206
|
-
temp_list = []
|
|
207
|
-
for lyr_name in list(pdef_data.GetLayerNames()):
|
|
208
|
-
result = pdef_data.GetPadParametersValue(lyr_name, pad_type)
|
|
209
|
-
_, pad_shape, params, offset_x, offset_y, rotation = result
|
|
210
|
-
pad_shape = pascal_to_snake(pad_shape.ToString())
|
|
211
|
-
|
|
212
|
-
pad_params = {}
|
|
213
|
-
pad_params["layer_name"] = lyr_name
|
|
214
|
-
pad_params["shape"] = pad_shape
|
|
215
|
-
pad_params["offset_x"] = offset_x.ToString()
|
|
216
|
-
pad_params["offset_y"] = offset_y.ToString()
|
|
217
|
-
pad_params["rotation"] = rotation.ToString()
|
|
218
|
-
|
|
219
|
-
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[pad_shape]):
|
|
220
|
-
pad_params[i] = params[idx].ToString()
|
|
221
|
-
temp_list.append(pad_params)
|
|
222
|
-
data[pad_type_name] = temp_list
|
|
223
|
-
return data
|
|
224
|
-
|
|
225
|
-
def _set_pad_parameters_to_edb(self, param):
|
|
226
|
-
pdef_data = self._pyedb_obj._padstack_def_data
|
|
227
|
-
|
|
228
|
-
pad_type_list = [
|
|
229
|
-
self._pedb._edb.Definition.PadType.RegularPad,
|
|
230
|
-
self._pedb._edb.Definition.PadType.AntiPad,
|
|
231
|
-
self._pedb._edb.Definition.PadType.ThermalPad,
|
|
232
|
-
self._pedb._edb.Definition.PadType.Hole,
|
|
233
|
-
]
|
|
234
|
-
for pad_type in pad_type_list:
|
|
235
|
-
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
236
|
-
rpp = param.get(pad_type_name, [])
|
|
237
|
-
for idx, layer_data in enumerate(rpp):
|
|
238
|
-
# Get geometry type from kwargs
|
|
239
|
-
p = layer_data.get("shape")
|
|
240
|
-
temp_param = []
|
|
241
|
-
|
|
242
|
-
# Handle Circle geometry type
|
|
243
|
-
if p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Circle.ToString()):
|
|
244
|
-
temp_param.append(layer_data["diameter"])
|
|
245
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Circle
|
|
246
|
-
|
|
247
|
-
# Handle Square geometry type
|
|
248
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Square.ToString()):
|
|
249
|
-
temp_param.append(layer_data["size"])
|
|
250
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Square
|
|
251
|
-
|
|
252
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Rectangle.ToString()):
|
|
253
|
-
temp_param.append(layer_data["x_size"])
|
|
254
|
-
temp_param.append(layer_data["y_size"])
|
|
255
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Rectangle
|
|
256
|
-
|
|
257
|
-
# Handle Oval geometry type
|
|
258
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Oval.ToString()):
|
|
259
|
-
temp_param.append(layer_data["x_size"])
|
|
260
|
-
temp_param.append(layer_data["y_size"])
|
|
261
|
-
temp_param.append(layer_data["corner_radius"])
|
|
262
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Oval
|
|
263
|
-
|
|
264
|
-
# Handle Bullet geometry type
|
|
265
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Bullet.ToString()):
|
|
266
|
-
temp_param.append(layer_data["x_size"])
|
|
267
|
-
temp_param.append(layer_data["y_size"])
|
|
268
|
-
temp_param.append(layer_data["corner_radius"])
|
|
269
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Bullet
|
|
270
|
-
|
|
271
|
-
# Handle Round45 geometry type
|
|
272
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Round45.ToString()):
|
|
273
|
-
temp_param.append(layer_data["inner"])
|
|
274
|
-
temp_param.append(layer_data["channel_width"])
|
|
275
|
-
temp_param.append(layer_data["isolation_gap"])
|
|
276
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Round45
|
|
277
|
-
|
|
278
|
-
# Handle Round90 geometry type
|
|
279
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.Round90.ToString()):
|
|
280
|
-
temp_param.append(layer_data["inner"])
|
|
281
|
-
temp_param.append(layer_data["channel_width"])
|
|
282
|
-
temp_param.append(layer_data["isolation_gap"])
|
|
283
|
-
pad_shape = self._pedb._edb.Definition.PadGeometryType.Round90
|
|
284
|
-
elif p == pascal_to_snake(self._pedb._edb.Definition.PadGeometryType.NoGeometry.ToString()):
|
|
285
|
-
continue
|
|
286
|
-
|
|
287
|
-
# Set pad parameters for the current layer
|
|
288
|
-
pdef_data.SetPadParameters(
|
|
289
|
-
layer_data["layer_name"],
|
|
290
|
-
pad_type,
|
|
291
|
-
pad_shape,
|
|
292
|
-
convert_py_list_to_net_list([self._pedb.edb_value(i) for i in temp_param]),
|
|
293
|
-
self._pedb.edb_value(layer_data.get("offset_x", 0)),
|
|
294
|
-
self._pedb.edb_value(layer_data.get("offset_y", 0)),
|
|
295
|
-
self._pedb.edb_value(layer_data.get("rotation", 0)),
|
|
363
|
+
class Common:
|
|
364
|
+
@property
|
|
365
|
+
def pyedb_obj(self):
|
|
366
|
+
return self.parent.pyedb_obj
|
|
367
|
+
|
|
368
|
+
def __init__(self, parent):
|
|
369
|
+
self.parent = parent
|
|
370
|
+
self.pedb = parent.pedb
|
|
371
|
+
|
|
372
|
+
def set_parameters_to_edb(self):
|
|
373
|
+
if self.parent.name is not None:
|
|
374
|
+
self.pyedb_obj.aedt_name = self.parent.name
|
|
375
|
+
if self.parent.net_name is not None:
|
|
376
|
+
self.pyedb_obj.net_name = self.pedb.nets.find_or_create_net(self.parent.net_name).name
|
|
377
|
+
if self.parent.layer_range[0] is not None:
|
|
378
|
+
self.pyedb_obj.start_layer = self.parent.layer_range[0]
|
|
379
|
+
if self.parent.layer_range[1] is not None:
|
|
380
|
+
self.pyedb_obj.stop_layer = self.parent.layer_range[1]
|
|
381
|
+
if self.parent.backdrill_parameters:
|
|
382
|
+
self.pyedb_obj.backdrill_parameters = self.parent.backdrill_parameters
|
|
383
|
+
if self.parent.solder_ball_layer:
|
|
384
|
+
self.pyedb_obj._edb_object.SetSolderBallLayer(
|
|
385
|
+
self.pedb.stackup[self.parent.solder_ball_layer]._edb_object
|
|
296
386
|
)
|
|
297
|
-
self._pyedb_obj._padstack_def_data = pdef_data
|
|
298
|
-
|
|
299
|
-
def _get_hole_parameters_from_edb(self):
|
|
300
|
-
pdef_data = self._pyedb_obj._padstack_def_data
|
|
301
|
-
_, hole_shape, params, offset_x, offset_y, rotation = pdef_data.GetHoleParametersValue()
|
|
302
|
-
hole_shape = pascal_to_snake(hole_shape.ToString())
|
|
303
|
-
|
|
304
|
-
hole_params = {}
|
|
305
|
-
hole_params["shape"] = hole_shape
|
|
306
|
-
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[hole_shape]):
|
|
307
|
-
hole_params[i] = params[idx].ToString()
|
|
308
|
-
hole_params["offset_x"] = offset_x.ToString()
|
|
309
|
-
hole_params["offset_y"] = offset_y.ToString()
|
|
310
|
-
hole_params["rotation"] = rotation.ToString()
|
|
311
|
-
return hole_params
|
|
312
|
-
|
|
313
|
-
def _set_hole_parameters_to_edb(self, params):
|
|
314
|
-
original_params = self.hole_parameters
|
|
315
|
-
pdef_data = self._pyedb_obj._padstack_def_data
|
|
316
|
-
|
|
317
|
-
temp_param = []
|
|
318
|
-
shape = params["shape"]
|
|
319
|
-
if shape == "no_geometry":
|
|
320
|
-
return # .net api doesn't tell how to set no_geometry shape.
|
|
321
|
-
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[shape]):
|
|
322
|
-
temp_param.append(params[i])
|
|
323
|
-
pedb_shape = getattr(self._pedb._edb.Definition.PadGeometryType, snake_to_pascal(shape))
|
|
324
|
-
|
|
325
|
-
pdef_data.SetHoleParameters(
|
|
326
|
-
pedb_shape,
|
|
327
|
-
convert_py_list_to_net_list([self._pedb.edb_value(i) for i in temp_param]),
|
|
328
|
-
self._pedb.edb_value(params.get("offset_x", original_params.get("offset_x", 0))),
|
|
329
|
-
self._pedb.edb_value(params.get("offset_y", original_params.get("offset_y", 0))),
|
|
330
|
-
self._pedb.edb_value(params.get("rotation", original_params.get("rotation", 0))),
|
|
331
|
-
)
|
|
332
|
-
self._pyedb_obj._padstack_def_data = pdef_data
|
|
333
387
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
388
|
+
hole_override_enabled, hole_override_diam = self.pyedb_obj._edb_object.GetHoleOverrideValue()
|
|
389
|
+
hole_override_enabled = (
|
|
390
|
+
self.parent.hole_override_enabled if self.parent.hole_override_enabled else hole_override_enabled
|
|
391
|
+
)
|
|
392
|
+
hole_override_diam = (
|
|
393
|
+
self.parent.hole_override_diameter if self.parent.hole_override_diameter else hole_override_diam
|
|
394
|
+
)
|
|
395
|
+
self.pyedb_obj._edb_object.SetHoleOverride(hole_override_enabled, self.pedb.edb_value(hole_override_diam))
|
|
396
|
+
|
|
397
|
+
def retrieve_parameters_from_edb(self):
|
|
398
|
+
self.parent.name = self.pyedb_obj.aedt_name
|
|
399
|
+
self.parent.definition = self.pyedb_obj.padstack_definition
|
|
400
|
+
self.parent.backdrill_parameters = self.pyedb_obj.backdrill_parameters
|
|
401
|
+
_, position, rotation = self.pyedb_obj._edb_object.GetPositionAndRotationValue()
|
|
402
|
+
self.parent.position = [position.X.ToString(), position.Y.ToString()]
|
|
403
|
+
self.parent.rotation = rotation.ToString()
|
|
404
|
+
self.parent._id = self.pyedb_obj.id
|
|
405
|
+
(
|
|
406
|
+
self.parent.hole_override_enabled,
|
|
407
|
+
hole_override_diameter,
|
|
408
|
+
) = self.pyedb_obj._edb_object.GetHoleOverrideValue()
|
|
409
|
+
self.parent.hole_override_diameter = hole_override_diameter.ToString()
|
|
410
|
+
self.parent.solder_ball_layer = self.pyedb_obj._edb_object.GetSolderBallLayer().GetName()
|
|
411
|
+
self.parent.layer_range = [self.pyedb_obj.start_layer, self.pyedb_obj.stop_layer]
|
|
412
|
+
|
|
413
|
+
class Grpc(Common):
|
|
414
|
+
def __init__(self, parent):
|
|
415
|
+
super().__init__(parent)
|
|
416
|
+
|
|
417
|
+
class DotNet(Grpc):
|
|
418
|
+
def __init__(self, parent):
|
|
419
|
+
super().__init__(parent)
|
|
337
420
|
|
|
338
421
|
def __init__(self, pedb, pyedb_obj, **kwargs):
|
|
339
|
-
self.
|
|
340
|
-
self.
|
|
422
|
+
self.pedb = pedb
|
|
423
|
+
self.pyedb_obj = pyedb_obj
|
|
424
|
+
if os.environ["PYEDB_USE_DOTNET"] == "0":
|
|
425
|
+
self.api = self.Grpc(self)
|
|
426
|
+
else:
|
|
427
|
+
self.api = self.DotNet(self)
|
|
428
|
+
|
|
341
429
|
self.name = kwargs.get("name", None)
|
|
342
430
|
self.net_name = kwargs.get("net_name", "")
|
|
343
431
|
self.layer_range = kwargs.get("layer_range", [None, None])
|
|
@@ -349,35 +437,3 @@ class CfgPadstackInstance(CfgBase):
|
|
|
349
437
|
self.hole_override_enabled = kwargs.get("hole_override_enabled", None)
|
|
350
438
|
self.hole_override_diameter = kwargs.get("hole_override_diameter", None)
|
|
351
439
|
self.solder_ball_layer = kwargs.get("solder_ball_layer", None)
|
|
352
|
-
|
|
353
|
-
def set_parameters_to_edb(self):
|
|
354
|
-
if self.name is not None:
|
|
355
|
-
self._pyedb_obj.aedt_name = self.name
|
|
356
|
-
if self.net_name is not None:
|
|
357
|
-
self._pyedb_obj.net_name = self._pedb.nets.find_or_create_net(self.net_name).name
|
|
358
|
-
if self.layer_range[0] is not None:
|
|
359
|
-
self._pyedb_obj.start_layer = self.layer_range[0]
|
|
360
|
-
if self.layer_range[1] is not None:
|
|
361
|
-
self._pyedb_obj.stop_layer = self.layer_range[1]
|
|
362
|
-
if self.backdrill_parameters:
|
|
363
|
-
self._pyedb_obj.backdrill_parameters = self.backdrill_parameters
|
|
364
|
-
if self.solder_ball_layer:
|
|
365
|
-
self._pyedb_obj._edb_object.SetSolderBallLayer(self._pedb.stackup[self.solder_ball_layer]._edb_object)
|
|
366
|
-
|
|
367
|
-
hole_override_enabled, hole_override_diam = self._pyedb_obj._edb_object.GetHoleOverrideValue()
|
|
368
|
-
hole_override_enabled = self.hole_override_enabled if self.hole_override_enabled else hole_override_enabled
|
|
369
|
-
hole_override_diam = self.hole_override_diameter if self.hole_override_diameter else hole_override_diam
|
|
370
|
-
self._pyedb_obj._edb_object.SetHoleOverride(hole_override_enabled, self._pedb.edb_value(hole_override_diam))
|
|
371
|
-
|
|
372
|
-
def retrieve_parameters_from_edb(self):
|
|
373
|
-
self.name = self._pyedb_obj.aedt_name
|
|
374
|
-
self.definition = self._pyedb_obj.padstack_definition
|
|
375
|
-
self.backdrill_parameters = self._pyedb_obj.backdrill_parameters
|
|
376
|
-
_, position, rotation = self._pyedb_obj._edb_object.GetPositionAndRotationValue()
|
|
377
|
-
self.position = [position.X.ToString(), position.Y.ToString()]
|
|
378
|
-
self.rotation = rotation.ToString()
|
|
379
|
-
self._id = self._pyedb_obj.id
|
|
380
|
-
self.hole_override_enabled, hole_override_diameter = self._pyedb_obj._edb_object.GetHoleOverrideValue()
|
|
381
|
-
self.hole_override_diameter = hole_override_diameter.ToString()
|
|
382
|
-
self.solder_ball_layer = self._pyedb_obj._edb_object.GetSolderBallLayer().GetName()
|
|
383
|
-
self.layer_range = [self._pyedb_obj.start_layer, self._pyedb_obj.stop_layer]
|