pyedb 0.31.0__py3-none-any.whl → 0.34.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 -27
- pyedb/common/__init__.py +0 -0
- pyedb/common/nets.py +488 -0
- pyedb/configuration/cfg_common.py +20 -0
- pyedb/configuration/cfg_components.py +218 -57
- pyedb/configuration/cfg_data.py +6 -0
- pyedb/configuration/cfg_modeler.py +139 -0
- pyedb/configuration/cfg_operations.py +5 -4
- pyedb/configuration/cfg_padstacks.py +319 -55
- pyedb/configuration/cfg_ports_sources.py +99 -7
- pyedb/configuration/cfg_s_parameter_models.py +6 -6
- pyedb/configuration/configuration.py +31 -9
- pyedb/dotnet/clr_module.py +92 -32
- pyedb/dotnet/edb.py +54 -5
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +0 -202
- pyedb/dotnet/edb_core/cell/layout.py +1 -1
- pyedb/dotnet/edb_core/cell/primitive/primitive.py +5 -27
- pyedb/dotnet/edb_core/edb_data/control_file.py +21 -0
- pyedb/dotnet/edb_core/edb_data/nets_data.py +6 -1
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +16 -222
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +31 -0
- pyedb/dotnet/edb_core/hfss.py +2 -2
- pyedb/dotnet/edb_core/layout_validation.py +1 -3
- pyedb/dotnet/edb_core/materials.py +38 -38
- pyedb/dotnet/edb_core/modeler.py +4 -1
- pyedb/dotnet/edb_core/nets.py +2 -373
- pyedb/generic/filesystem.py +2 -5
- {pyedb-0.31.0.dist-info → pyedb-0.34.0.dist-info}/METADATA +12 -9
- {pyedb-0.31.0.dist-info → pyedb-0.34.0.dist-info}/RECORD +31 -28
- {pyedb-0.31.0.dist-info → pyedb-0.34.0.dist-info}/WHEEL +1 -1
- {pyedb-0.31.0.dist-info → pyedb-0.34.0.dist-info}/LICENSE +0 -0
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
23
|
from pyedb.configuration.cfg_common import CfgBase
|
|
24
|
+
from pyedb.dotnet.edb_core.general import (
|
|
25
|
+
convert_py_list_to_net_list,
|
|
26
|
+
pascal_to_snake,
|
|
27
|
+
snake_to_pascal,
|
|
28
|
+
)
|
|
24
29
|
|
|
25
30
|
|
|
26
31
|
class CfgPadstacks:
|
|
@@ -30,90 +35,349 @@ class CfgPadstacks:
|
|
|
30
35
|
self._pedb = pedb
|
|
31
36
|
self.definitions = []
|
|
32
37
|
self.instances = []
|
|
38
|
+
|
|
33
39
|
if padstack_dict:
|
|
40
|
+
padstack_defs_layout = self._pedb.padstacks.definitions
|
|
34
41
|
for pdef in padstack_dict.get("definitions", []):
|
|
35
|
-
|
|
42
|
+
obj = padstack_defs_layout[pdef["name"]]
|
|
43
|
+
self.definitions.append(CfgPadstackDefinition(self._pedb, obj, **pdef))
|
|
44
|
+
|
|
45
|
+
inst_from_layout = self._pedb.padstacks.instances_by_name
|
|
36
46
|
for inst in padstack_dict.get("instances", []):
|
|
37
|
-
|
|
47
|
+
obj = inst_from_layout[inst["name"]]
|
|
48
|
+
self.instances.append(CfgPadstackInstance(self._pedb, obj, **inst))
|
|
49
|
+
|
|
50
|
+
def clean(self):
|
|
51
|
+
self.definitions = []
|
|
52
|
+
self.instances = []
|
|
38
53
|
|
|
39
54
|
def apply(self):
|
|
40
55
|
"""Apply padstack definition and instances on layout."""
|
|
41
56
|
if self.definitions:
|
|
42
|
-
padstack_defs_layout = self._pedb.padstacks.definitions
|
|
43
57
|
for pdef in self.definitions:
|
|
44
|
-
|
|
45
|
-
pdef_layout.set_properties(**pdef.get_attributes())
|
|
58
|
+
pdef.set_parameters_to_edb()
|
|
46
59
|
if self.instances:
|
|
47
|
-
instances_layout = self._pedb.padstacks.instances_by_name
|
|
48
60
|
for inst in self.instances:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
self.definitions.append(
|
|
60
|
-
Definition(
|
|
61
|
-
name=pdef_name,
|
|
62
|
-
hole_plating_thickness=pdef.hole_plating_thickness,
|
|
63
|
-
hole_material=pdef.material,
|
|
64
|
-
hole_range=pdef.hole_range,
|
|
65
|
-
pad_parameters=pdef.pad_parameters,
|
|
66
|
-
hole_parameters=pdef.hole_parameters,
|
|
67
|
-
)
|
|
68
|
-
)
|
|
69
|
-
data = {}
|
|
70
|
-
definitions = []
|
|
71
|
-
for i in self.definitions:
|
|
72
|
-
definitions.append(i.get_attributes())
|
|
73
|
-
data["definitions"] = definitions
|
|
61
|
+
inst.set_parameters_to_edb()
|
|
62
|
+
|
|
63
|
+
def retrieve_parameters_from_edb(self):
|
|
64
|
+
self.clean()
|
|
65
|
+
for name, obj in self._pedb.padstacks.definitions.items():
|
|
66
|
+
if name.lower() == "symbol":
|
|
67
|
+
continue
|
|
68
|
+
pdef = CfgPadstackDefinition(self._pedb, obj)
|
|
69
|
+
pdef.retrieve_parameters_from_edb()
|
|
70
|
+
self.definitions.append(pdef)
|
|
74
71
|
|
|
75
72
|
for obj in self._pedb.layout.padstack_instances:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
name=temp["name"],
|
|
80
|
-
definition=temp["definition"],
|
|
81
|
-
backdrill_parameters=temp["backdrill_parameters"],
|
|
82
|
-
id=temp["id"],
|
|
83
|
-
position=temp["position"],
|
|
84
|
-
rotation=temp["rotation"],
|
|
85
|
-
hole_override_enabled=temp["hole_override_enabled"],
|
|
86
|
-
hole_override_diameter=temp["hole_override_diameter"],
|
|
87
|
-
)
|
|
88
|
-
)
|
|
89
|
-
instances = []
|
|
90
|
-
for i in self.instances:
|
|
91
|
-
instances.append(i.get_attributes("id"))
|
|
92
|
-
data["instances"] = instances
|
|
93
|
-
return data
|
|
73
|
+
inst = CfgPadstackInstance(self._pedb, obj)
|
|
74
|
+
inst.retrieve_parameters_from_edb()
|
|
75
|
+
self.instances.append(inst)
|
|
94
76
|
|
|
95
77
|
|
|
96
|
-
class
|
|
78
|
+
class CfgPadstackDefinition(CfgBase):
|
|
97
79
|
"""Padstack definition data class."""
|
|
98
80
|
|
|
99
|
-
|
|
81
|
+
PAD_SHAPE_PARAMETERS = {
|
|
82
|
+
"circle": ["diameter"],
|
|
83
|
+
"square": ["size"],
|
|
84
|
+
"rectangle": ["x_size", "y_size"],
|
|
85
|
+
"oval": ["x_size", "y_size", "corner_radius"],
|
|
86
|
+
"bullet": ["x_size", "y_size", "corner_radius"],
|
|
87
|
+
"round45": ["inner", "channel_width", "isolation_gap"],
|
|
88
|
+
"round90": ["inner", "channel_width", "isolation_gap"],
|
|
89
|
+
"no_geometry": [],
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
def __init__(self, pedb, pedb_object, **kwargs):
|
|
93
|
+
self._pedb = pedb
|
|
94
|
+
self._pyedb_obj = pedb_object
|
|
100
95
|
self.name = kwargs.get("name", None)
|
|
101
96
|
self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None)
|
|
102
97
|
self.material = kwargs.get("hole_material", None)
|
|
103
98
|
self.hole_range = kwargs.get("hole_range", None)
|
|
104
99
|
self.pad_parameters = kwargs.get("pad_parameters", None)
|
|
105
100
|
self.hole_parameters = kwargs.get("hole_parameters", None)
|
|
101
|
+
self.solder_ball_parameters = kwargs.get("solder_ball_parameters", None)
|
|
102
|
+
|
|
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
|
+
|
|
113
|
+
def set_parameters_to_edb(self):
|
|
114
|
+
if self.hole_parameters:
|
|
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)
|
|
126
|
+
|
|
127
|
+
def _set_solder_parameters_to_edb(self, parameters):
|
|
128
|
+
pdef_data = self._pyedb_obj._padstack_def_data
|
|
129
|
+
|
|
130
|
+
shape = parameters.get("shape", "no_solder_ball")
|
|
131
|
+
diameter = parameters.get("diameter", "0.4mm")
|
|
132
|
+
mid_diameter = parameters.get("mid_diameter", diameter)
|
|
133
|
+
placement = parameters.get("placement", "above_padstack")
|
|
134
|
+
material = parameters.get("material", None)
|
|
135
|
+
|
|
136
|
+
pdef_data.SetSolderBallShape(self._solder_shape_type[shape])
|
|
137
|
+
if not shape == "no_solder_ball":
|
|
138
|
+
pdef_data.SetSolderBallParameter(self._pedb.edb_value(diameter), self._pedb.edb_value(mid_diameter))
|
|
139
|
+
pdef_data.SetSolderBallPlacement(self._solder_placement[placement])
|
|
106
140
|
|
|
141
|
+
if material:
|
|
142
|
+
pdef_data.SetSolderBallMaterial(material)
|
|
143
|
+
self._pyedb_obj._padstack_def_data = pdef_data
|
|
144
|
+
|
|
145
|
+
def _get_solder_parameters_from_edb(self):
|
|
146
|
+
pdef_data = self._pyedb_obj._padstack_def_data
|
|
147
|
+
shape = pdef_data.GetSolderBallShape()
|
|
148
|
+
_, diameter, mid_diameter = pdef_data.GetSolderBallParameterValue()
|
|
149
|
+
placement = pdef_data.GetSolderBallPlacement()
|
|
150
|
+
material = pdef_data.GetSolderBallMaterial()
|
|
151
|
+
|
|
152
|
+
parameters = {
|
|
153
|
+
"shape": [i for i, j in self._solder_shape_type.items() if j == shape][0],
|
|
154
|
+
"diameter": self._pedb.edb_value(diameter).ToString(),
|
|
155
|
+
"mid_diameter": self._pedb.edb_value(mid_diameter).ToString(),
|
|
156
|
+
"placement": [i for i, j in self._solder_placement.items() if j == placement][0],
|
|
157
|
+
"material": material,
|
|
158
|
+
}
|
|
159
|
+
return parameters
|
|
160
|
+
|
|
161
|
+
def retrieve_parameters_from_edb(self):
|
|
162
|
+
self.name = self._pyedb_obj.name
|
|
163
|
+
self.hole_plating_thickness = self._pyedb_obj.hole_plating_thickness
|
|
164
|
+
self.material = self._pyedb_obj.material
|
|
165
|
+
self.hole_range = self._pyedb_obj.hole_range
|
|
166
|
+
self.pad_parameters = self._get_pad_parameters_from_edb()
|
|
167
|
+
self.hole_parameters = self._get_hole_parameters_from_edb()
|
|
168
|
+
self.solder_ball_parameters = self._get_solder_parameters_from_edb()
|
|
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())
|
|
107
211
|
|
|
108
|
-
|
|
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)),
|
|
296
|
+
)
|
|
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
|
+
|
|
334
|
+
|
|
335
|
+
class CfgPadstackInstance(CfgBase):
|
|
109
336
|
"""Instance data class."""
|
|
110
337
|
|
|
111
|
-
def __init__(self, **kwargs):
|
|
112
|
-
self.
|
|
338
|
+
def __init__(self, pedb, pyedb_obj, **kwargs):
|
|
339
|
+
self._pedb = pedb
|
|
340
|
+
self._pyedb_obj = pyedb_obj
|
|
341
|
+
self.name = kwargs.get("name", None)
|
|
342
|
+
self.net_name = kwargs.get("net_name", "")
|
|
343
|
+
self.layer_range = kwargs.get("layer_range", [None, None])
|
|
113
344
|
self.definition = kwargs.get("definition", None)
|
|
114
345
|
self.backdrill_parameters = kwargs.get("backdrill_parameters", None)
|
|
115
|
-
self.
|
|
346
|
+
self._id = kwargs.get("id", None)
|
|
116
347
|
self.position = kwargs.get("position", [])
|
|
117
348
|
self.rotation = kwargs.get("rotation", None)
|
|
118
349
|
self.hole_override_enabled = kwargs.get("hole_override_enabled", None)
|
|
119
350
|
self.hole_override_diameter = kwargs.get("hole_override_diameter", None)
|
|
351
|
+
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]
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
23
|
from pyedb.configuration.cfg_common import CfgBase
|
|
24
|
+
from pyedb.dotnet.edb_core.edb_data.ports import WavePort
|
|
25
|
+
from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
26
|
+
from pyedb.dotnet.edb_core.geometry.point_data import PointData
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
class CfgTerminalInfo(CfgBase):
|
|
@@ -65,7 +68,7 @@ class CfgSources:
|
|
|
65
68
|
|
|
66
69
|
def apply(self):
|
|
67
70
|
for src in self.sources:
|
|
68
|
-
src.
|
|
71
|
+
src.set_parameters_to_edb()
|
|
69
72
|
|
|
70
73
|
def get_data_from_db(self):
|
|
71
74
|
self.sources = []
|
|
@@ -114,11 +117,28 @@ class CfgSources:
|
|
|
114
117
|
class CfgPorts:
|
|
115
118
|
def __init__(self, pedb, ports_data):
|
|
116
119
|
self._pedb = pedb
|
|
117
|
-
|
|
120
|
+
|
|
121
|
+
self.ports = []
|
|
122
|
+
for p in ports_data:
|
|
123
|
+
if p["type"] == "wave_port":
|
|
124
|
+
self.ports.append(CfgWavePort(self._pedb, **p))
|
|
125
|
+
elif p["type"] == "diff_wave_port":
|
|
126
|
+
self.ports.append(CfgDiffWavePort(self._pedb, **p))
|
|
127
|
+
elif p["type"] in ["coax", "circuit"]:
|
|
128
|
+
self.ports.append(CfgPort(self._pedb, **p))
|
|
129
|
+
else:
|
|
130
|
+
raise ValueError("Unknown port type")
|
|
118
131
|
|
|
119
132
|
def apply(self):
|
|
133
|
+
edb_primitives = {}
|
|
134
|
+
for i in self._pedb.layout.primitives:
|
|
135
|
+
if i.aedt_name:
|
|
136
|
+
edb_primitives[i.aedt_name] = i
|
|
120
137
|
for p in self.ports:
|
|
121
|
-
p.
|
|
138
|
+
if p.type in ["wave_port", "diff_wave_port"]:
|
|
139
|
+
p.set_parameters_to_edb(edb_primitives)
|
|
140
|
+
else:
|
|
141
|
+
p.set_parameters_to_edb()
|
|
122
142
|
|
|
123
143
|
def get_data_from_db(self):
|
|
124
144
|
self.ports = []
|
|
@@ -188,8 +208,8 @@ class CfgPorts:
|
|
|
188
208
|
class CfgCircuitElement(CfgBase):
|
|
189
209
|
def __init__(self, pedb, **kwargs):
|
|
190
210
|
self._pedb = pedb
|
|
191
|
-
self.name = kwargs
|
|
192
|
-
self.type = kwargs
|
|
211
|
+
self.name = kwargs["name"]
|
|
212
|
+
self.type = kwargs["type"]
|
|
193
213
|
self.reference_designator = kwargs.get("reference_designator", None)
|
|
194
214
|
self.distributed = kwargs.get("distributed", False)
|
|
195
215
|
|
|
@@ -321,7 +341,7 @@ class CfgPort(CfgCircuitElement):
|
|
|
321
341
|
def __init__(self, pedb, **kwargs):
|
|
322
342
|
super().__init__(pedb, **kwargs)
|
|
323
343
|
|
|
324
|
-
def
|
|
344
|
+
def set_parameters_to_edb(self):
|
|
325
345
|
"""Create port."""
|
|
326
346
|
self._create_terminals()
|
|
327
347
|
is_circuit_port = True if self.type == "circuit" else False
|
|
@@ -356,7 +376,7 @@ class CfgSource(CfgCircuitElement):
|
|
|
356
376
|
|
|
357
377
|
self.magnitude = kwargs.get("magnitude", 0.001)
|
|
358
378
|
|
|
359
|
-
def
|
|
379
|
+
def set_parameters_to_edb(self):
|
|
360
380
|
"""Create sources."""
|
|
361
381
|
self._create_terminals()
|
|
362
382
|
# is_circuit_port = True if self.type == "circuit" else False
|
|
@@ -385,3 +405,75 @@ class CfgSource(CfgCircuitElement):
|
|
|
385
405
|
"positive_terminal": self.positive_terminal_info.export_properties(),
|
|
386
406
|
"negative_terminal": self.negative_terminal_info.export_properties(),
|
|
387
407
|
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
class CfgWavePort:
|
|
411
|
+
def __init__(self, pedb, **kwargs):
|
|
412
|
+
self._pedb = pedb
|
|
413
|
+
self.name = kwargs["name"]
|
|
414
|
+
self.type = kwargs["type"]
|
|
415
|
+
self.primitive_name = kwargs["primitive_name"]
|
|
416
|
+
self.point_on_edge = kwargs["point_on_edge"]
|
|
417
|
+
self.horizontal_extent_factor = kwargs.get("horizontal_extent_factor", 5)
|
|
418
|
+
self.vertical_extent_factor = kwargs.get("vertical_extent_factor", 3)
|
|
419
|
+
self.pec_launch_width = kwargs.get("pec_launch_width", "0.01mm")
|
|
420
|
+
|
|
421
|
+
def set_parameters_to_edb(self, edb_primitives):
|
|
422
|
+
point_on_edge = PointData(self._pedb, x=self.point_on_edge[0], y=self.point_on_edge[1])
|
|
423
|
+
primitive = edb_primitives[self.primitive_name]
|
|
424
|
+
pos_edge = self._pedb.edb_api.cell.terminal.PrimitiveEdge.Create(
|
|
425
|
+
primitive._edb_object, point_on_edge._edb_object
|
|
426
|
+
)
|
|
427
|
+
pos_edge = convert_py_list_to_net_list(pos_edge, self._pedb.edb_api.cell.terminal.Edge)
|
|
428
|
+
edge_term = self._pedb.edb_api.cell.terminal.EdgeTerminal.Create(
|
|
429
|
+
primitive._edb_object.GetLayout(), primitive._edb_object.GetNet(), self.name, pos_edge, isRef=False
|
|
430
|
+
)
|
|
431
|
+
edge_term.SetImpedance(self._pedb.edb_value(50))
|
|
432
|
+
wave_port = WavePort(self._pedb, edge_term)
|
|
433
|
+
wave_port.horizontal_extent_factor = self.horizontal_extent_factor
|
|
434
|
+
wave_port.vertical_extent_factor = self.vertical_extent_factor
|
|
435
|
+
wave_port.pec_launch_width = self.pec_launch_width
|
|
436
|
+
wave_port.hfss_type = "Wave"
|
|
437
|
+
wave_port.do_renormalize = True
|
|
438
|
+
return wave_port
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class CfgDiffWavePort:
|
|
442
|
+
def __init__(self, pedb, **kwargs):
|
|
443
|
+
self._pedb = pedb
|
|
444
|
+
self.name = kwargs["name"]
|
|
445
|
+
self.type = kwargs["type"]
|
|
446
|
+
self.horizontal_extent_factor = kwargs.get("horizontal_extent_factor", 5)
|
|
447
|
+
self.vertical_extent_factor = kwargs.get("vertical_extent_factor", 3)
|
|
448
|
+
self.pec_launch_width = kwargs.get("pec_launch_width", "0.01mm")
|
|
449
|
+
|
|
450
|
+
kwargs["positive_terminal"]["type"] = "wave_port"
|
|
451
|
+
kwargs["positive_terminal"]["name"] = self.name + ":T1"
|
|
452
|
+
self.positive_port = CfgWavePort(
|
|
453
|
+
self._pedb,
|
|
454
|
+
horizontal_extent_factor=self.horizontal_extent_factor,
|
|
455
|
+
vertical_extent_factor=self.vertical_extent_factor,
|
|
456
|
+
pec_launch_width=self.pec_launch_width,
|
|
457
|
+
**kwargs["positive_terminal"],
|
|
458
|
+
)
|
|
459
|
+
kwargs["negative_terminal"]["type"] = "wave_port"
|
|
460
|
+
kwargs["negative_terminal"]["name"] = self.name + ":T2"
|
|
461
|
+
self.negative_port = CfgWavePort(
|
|
462
|
+
self._pedb,
|
|
463
|
+
horizontal_extent_factor=self.horizontal_extent_factor,
|
|
464
|
+
vertical_extent_factor=self.vertical_extent_factor,
|
|
465
|
+
pec_launch_width=self.pec_launch_width,
|
|
466
|
+
**kwargs["negative_terminal"],
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
def set_parameters_to_edb(self, edb_primitives):
|
|
470
|
+
pos_term = self.positive_port.set_parameters_to_edb(edb_primitives)
|
|
471
|
+
neg_term = self.negative_port.set_parameters_to_edb(edb_primitives)
|
|
472
|
+
edb_list = convert_py_list_to_net_list(
|
|
473
|
+
[pos_term._edb_object, neg_term._edb_object], self._pedb.edb_api.cell.terminal.Terminal
|
|
474
|
+
)
|
|
475
|
+
_edb_boundle_terminal = self._pedb.edb_api.cell.terminal.BundleTerminal.Create(edb_list)
|
|
476
|
+
_edb_boundle_terminal.SetName(self.name)
|
|
477
|
+
pos, neg = list(_edb_boundle_terminal.GetTerminals())
|
|
478
|
+
pos.SetName(self.name + ":T1")
|
|
479
|
+
neg.SetName(self.name + ":T2")
|
|
@@ -67,7 +67,7 @@ class CfgSParameters:
|
|
|
67
67
|
ref_net = s_param.reference_net
|
|
68
68
|
comp.use_s_parameter_model(s_param.name, reference_net=ref_net)
|
|
69
69
|
|
|
70
|
-
def get_data_from_db(self):
|
|
70
|
+
def get_data_from_db(self, cfg_components):
|
|
71
71
|
db_comp_def = self._pedb.definitions.component
|
|
72
72
|
for name, compdef_obj in db_comp_def.items():
|
|
73
73
|
nport_models = compdef_obj.component_models
|
|
@@ -75,16 +75,16 @@ class CfgSParameters:
|
|
|
75
75
|
continue
|
|
76
76
|
else:
|
|
77
77
|
pin_order = compdef_obj.get_properties()["pin_order"]
|
|
78
|
-
temp_comps =
|
|
78
|
+
temp_comps = [i for i in cfg_components if i["definition"] == name]
|
|
79
79
|
for model_name, model_obj in nport_models.items():
|
|
80
80
|
temp_comp_list = []
|
|
81
81
|
reference_net_per_component = {}
|
|
82
|
-
for i in temp_comps
|
|
83
|
-
s_param_model = i.
|
|
82
|
+
for i in temp_comps:
|
|
83
|
+
s_param_model = i.get("s_parameter_model")
|
|
84
84
|
if s_param_model:
|
|
85
85
|
if s_param_model["model_name"] == model_name:
|
|
86
|
-
temp_comp_list.append(i
|
|
87
|
-
reference_net_per_component[i
|
|
86
|
+
temp_comp_list.append(i["reference_designator"])
|
|
87
|
+
reference_net_per_component[i["reference_designator"]] = s_param_model["reference_net"]
|
|
88
88
|
else:
|
|
89
89
|
continue
|
|
90
90
|
|