pyedb 0.30.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 +321 -54
- 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 +59 -10
- 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 -205
- 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 -368
- pyedb/generic/filesystem.py +2 -5
- {pyedb-0.30.0.dist-info → pyedb-0.34.0.dist-info}/METADATA +14 -11
- {pyedb-0.30.0.dist-info → pyedb-0.34.0.dist-info}/RECORD +31 -28
- {pyedb-0.30.0.dist-info → pyedb-0.34.0.dist-info}/WHEEL +1 -1
- {pyedb-0.30.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,87 +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
|
-
for pdef_name, pdef in self._pedb.padstacks.definitions.items():
|
|
60
|
-
self.definitions.append(
|
|
61
|
-
Definition(
|
|
62
|
-
name=pdef_name,
|
|
63
|
-
hole_plating_thickness=pdef.hole_plating_thickness,
|
|
64
|
-
hole_material=pdef.material,
|
|
65
|
-
hole_range=pdef.hole_range,
|
|
66
|
-
pad_parameters=pdef.pad_parameters,
|
|
67
|
-
hole_parameters=pdef.hole_parameters,
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
data = {}
|
|
71
|
-
definitions = []
|
|
72
|
-
for i in self.definitions:
|
|
73
|
-
definitions.append(i.get_attributes())
|
|
74
|
-
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)
|
|
75
71
|
|
|
76
72
|
for obj in self._pedb.layout.padstack_instances:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
name=temp["name"],
|
|
81
|
-
definition=temp["definition"],
|
|
82
|
-
backdrill_parameters=temp["backdrill_parameters"],
|
|
83
|
-
id=temp["id"],
|
|
84
|
-
position=temp["position"],
|
|
85
|
-
rotation=temp["rotation"],
|
|
86
|
-
)
|
|
87
|
-
)
|
|
88
|
-
instances = []
|
|
89
|
-
for i in self.instances:
|
|
90
|
-
instances.append(i.get_attributes("id"))
|
|
91
|
-
data["instances"] = instances
|
|
92
|
-
return data
|
|
73
|
+
inst = CfgPadstackInstance(self._pedb, obj)
|
|
74
|
+
inst.retrieve_parameters_from_edb()
|
|
75
|
+
self.instances.append(inst)
|
|
93
76
|
|
|
94
77
|
|
|
95
|
-
class
|
|
78
|
+
class CfgPadstackDefinition(CfgBase):
|
|
96
79
|
"""Padstack definition data class."""
|
|
97
80
|
|
|
98
|
-
|
|
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
|
|
99
95
|
self.name = kwargs.get("name", None)
|
|
100
96
|
self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None)
|
|
101
97
|
self.material = kwargs.get("hole_material", None)
|
|
102
98
|
self.hole_range = kwargs.get("hole_range", None)
|
|
103
99
|
self.pad_parameters = kwargs.get("pad_parameters", None)
|
|
104
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])
|
|
105
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())
|
|
106
211
|
|
|
107
|
-
|
|
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):
|
|
108
336
|
"""Instance data class."""
|
|
109
337
|
|
|
110
|
-
def __init__(self, **kwargs):
|
|
111
|
-
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])
|
|
112
344
|
self.definition = kwargs.get("definition", None)
|
|
113
345
|
self.backdrill_parameters = kwargs.get("backdrill_parameters", None)
|
|
114
|
-
self.
|
|
346
|
+
self._id = kwargs.get("id", None)
|
|
115
347
|
self.position = kwargs.get("position", [])
|
|
116
348
|
self.rotation = kwargs.get("rotation", None)
|
|
349
|
+
self.hole_override_enabled = kwargs.get("hole_override_enabled", None)
|
|
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
|
|