pyedb 0.31.0__py3-none-any.whl → 0.34.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (32) hide show
  1. pyedb/__init__.py +1 -27
  2. pyedb/common/__init__.py +0 -0
  3. pyedb/common/nets.py +488 -0
  4. pyedb/configuration/cfg_common.py +20 -0
  5. pyedb/configuration/cfg_components.py +218 -57
  6. pyedb/configuration/cfg_data.py +6 -0
  7. pyedb/configuration/cfg_modeler.py +139 -0
  8. pyedb/configuration/cfg_operations.py +5 -4
  9. pyedb/configuration/cfg_padstacks.py +319 -55
  10. pyedb/configuration/cfg_ports_sources.py +99 -7
  11. pyedb/configuration/cfg_s_parameter_models.py +6 -6
  12. pyedb/configuration/configuration.py +31 -9
  13. pyedb/dotnet/clr_module.py +92 -32
  14. pyedb/dotnet/edb.py +54 -5
  15. pyedb/dotnet/edb_core/cell/hierarchy/component.py +0 -202
  16. pyedb/dotnet/edb_core/cell/layout.py +1 -1
  17. pyedb/dotnet/edb_core/cell/primitive/primitive.py +5 -27
  18. pyedb/dotnet/edb_core/edb_data/control_file.py +21 -0
  19. pyedb/dotnet/edb_core/edb_data/layer_data.py +60 -6
  20. pyedb/dotnet/edb_core/edb_data/nets_data.py +6 -1
  21. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +16 -222
  22. pyedb/dotnet/edb_core/edb_data/primitives_data.py +31 -0
  23. pyedb/dotnet/edb_core/hfss.py +2 -2
  24. pyedb/dotnet/edb_core/layout_validation.py +1 -3
  25. pyedb/dotnet/edb_core/materials.py +38 -38
  26. pyedb/dotnet/edb_core/modeler.py +4 -1
  27. pyedb/dotnet/edb_core/nets.py +2 -373
  28. pyedb/generic/filesystem.py +2 -5
  29. {pyedb-0.31.0.dist-info → pyedb-0.34.1.dist-info}/METADATA +12 -9
  30. {pyedb-0.31.0.dist-info → pyedb-0.34.1.dist-info}/RECORD +32 -29
  31. {pyedb-0.31.0.dist-info → pyedb-0.34.1.dist-info}/WHEEL +1 -1
  32. {pyedb-0.31.0.dist-info → pyedb-0.34.1.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
- self.definitions.append(Definition(**pdef))
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
- self.instances.append(Instance(**inst))
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
- pdef_layout = padstack_defs_layout[pdef.name]
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
- inst_layout = instances_layout[inst.name]
50
- data = dict()
51
- data["backdrill_parameters"] = inst.backdrill_parameters
52
- data["hole_override_enabled"] = inst.hole_override_enabled
53
- data["hole_override_diameter"] = inst.hole_override_diameter
54
- inst_layout.properties = data
55
-
56
- def get_data_from_db(self):
57
- self.definitions = []
58
- for pdef_name, pdef in self._pedb.padstacks.definitions.items():
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
- temp = obj.properties
77
- self.instances.append(
78
- Instance(
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 Definition(CfgBase):
78
+ class CfgPadstackDefinition(CfgBase):
97
79
  """Padstack definition data class."""
98
80
 
99
- def __init__(self, **kwargs):
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
- class Instance(CfgBase):
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.name = kwargs["name"]
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.id = kwargs.get("id", None)
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.create()
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
- self.ports = [CfgPort(self._pedb, **p) for p in ports_data]
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.create()
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.get("name", None)
192
- self.type = kwargs.get("type", None)
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 create(self):
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 create(self):
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 = compdef_obj.components
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.values():
83
- s_param_model = i.model_properties.get("s_parameter_model")
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.refdes)
87
- reference_net_per_component[i.refdes] = s_param_model["reference_net"]
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