pyedb 0.16.0__py3-none-any.whl → 0.18.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_components.py +47 -1
- pyedb/configuration/configuration.py +2 -0
- pyedb/dotnet/edb.py +133 -64
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +12 -17
- pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +50 -0
- pyedb/dotnet/edb_core/cell/layout.py +0 -6
- pyedb/dotnet/edb_core/cell/voltage_regulator.py +0 -5
- pyedb/dotnet/edb_core/components.py +2 -2
- pyedb/dotnet/edb_core/dotnet/primitive.py +129 -3
- pyedb/dotnet/edb_core/edb_data/hfss_pi_simulation_setup_data.py +0 -460
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +38 -38
- pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py +1 -1
- pyedb/dotnet/edb_core/layout.py +21 -0
- pyedb/dotnet/edb_core/layout_validation.py +26 -0
- pyedb/dotnet/edb_core/nets.py +1 -1
- pyedb/dotnet/edb_core/sim_setup_data/data/sim_setup_info.py +1 -1
- pyedb/dotnet/edb_core/sim_setup_data/data/simulation_settings.py +357 -0
- pyedb/dotnet/edb_core/siwave.py +14 -0
- pyedb/dotnet/edb_core/utilities/hfss_simulation_setup.py +83 -0
- pyedb/dotnet/edb_core/utilities/simulation_setup.py +7 -4
- pyedb/misc/siw_feature_config/xtalk_scan/fd_xtalk_scan_config.py +91 -0
- pyedb/misc/siw_feature_config/xtalk_scan/impedance_scan_config.py +70 -0
- pyedb/misc/siw_feature_config/xtalk_scan/net.py +69 -0
- pyedb/misc/siw_feature_config/xtalk_scan/pins.py +60 -0
- pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +88 -0
- pyedb/misc/siw_feature_config/xtalk_scan/td_xtalk_config.py +104 -0
- pyedb/workflow.py +32 -0
- {pyedb-0.16.0.dist-info → pyedb-0.18.0.dist-info}/METADATA +1 -1
- {pyedb-0.16.0.dist-info → pyedb-0.18.0.dist-info}/RECORD +32 -24
- {pyedb-0.16.0.dist-info → pyedb-0.18.0.dist-info}/LICENSE +0 -0
- {pyedb-0.16.0.dist-info → pyedb-0.18.0.dist-info}/WHEEL +0 -0
|
@@ -65,3 +65,360 @@ class HFSSSimulationSettings(SimulationSettings):
|
|
|
65
65
|
@property
|
|
66
66
|
def mesh_operations(self):
|
|
67
67
|
return self._edb_object.MeshOperations
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class HFSSPISimulationSettings(SimulationSettings):
|
|
71
|
+
def __init__(self, edb_setup_info, pedb, edb_object):
|
|
72
|
+
super().__init__(pedb, edb_setup_info, edb_object)
|
|
73
|
+
self._pedb = pedb
|
|
74
|
+
self.logger = self._pedb.logger
|
|
75
|
+
self._edb_setup_info = edb_setup_info
|
|
76
|
+
self._simulation_settings = edb_setup_info.SimulationSettings
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def auto_select_nets_for_simulation(self):
|
|
80
|
+
"""Auto select nets for simulation.
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
bool
|
|
85
|
+
"""
|
|
86
|
+
return self._simulation_settings.AutoSelectNetsForSimulation
|
|
87
|
+
|
|
88
|
+
@auto_select_nets_for_simulation.setter
|
|
89
|
+
def auto_select_nets_for_simulation(self, value):
|
|
90
|
+
if isinstance(value, bool):
|
|
91
|
+
self._simulation_settings.AutoSelectNetsForSimulation = value
|
|
92
|
+
else:
|
|
93
|
+
self.logger.error(
|
|
94
|
+
"Property auto_select_nets_for_simulation expects a boolean "
|
|
95
|
+
f"value while the provided value is {value}."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def enabled(self):
|
|
100
|
+
return self._simulation_settings.Enabled
|
|
101
|
+
|
|
102
|
+
@enabled.setter
|
|
103
|
+
def enabled(self, value):
|
|
104
|
+
if isinstance(value, bool):
|
|
105
|
+
self._simulation_settings.Enabled = value
|
|
106
|
+
else:
|
|
107
|
+
self.logger.error(f"Property enabled expects a boolean value while the provided value is {value}.")
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def ignore_dummy_nets_for_selected_nets(self):
|
|
111
|
+
"""Auto select Nets for simulation
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
bool
|
|
116
|
+
"""
|
|
117
|
+
return self._simulation_settings.IgnoreDummyNetsForSelectedNets
|
|
118
|
+
|
|
119
|
+
@ignore_dummy_nets_for_selected_nets.setter
|
|
120
|
+
def ignore_dummy_nets_for_selected_nets(self, value):
|
|
121
|
+
if isinstance(value, bool):
|
|
122
|
+
self._simulation_settings.IgnoreDummyNetsForSelectedNets = value
|
|
123
|
+
else:
|
|
124
|
+
self.logger.error(
|
|
125
|
+
"Property ignore_dummy_nets_for_selected_nets expects a boolean "
|
|
126
|
+
f"value while the provided value is {value}."
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def ignore_small_holes(self):
|
|
131
|
+
"""Ignore small holes choice.
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
bool
|
|
136
|
+
"""
|
|
137
|
+
return self._simulation_settings.IgnoreSmallHoles
|
|
138
|
+
|
|
139
|
+
@ignore_small_holes.setter
|
|
140
|
+
def ignore_small_holes(self, value):
|
|
141
|
+
if isinstance(value, bool):
|
|
142
|
+
self._simulation_settings.IgnoreSmallHoles = value
|
|
143
|
+
else:
|
|
144
|
+
self.logger.error(
|
|
145
|
+
f"Property ignore_small_holes expects a boolean value while the provided value is {value}."
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def ignore_small_holes_min_diameter(self):
|
|
150
|
+
"""Min diameter to ignore small holes.
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
str
|
|
155
|
+
"""
|
|
156
|
+
return self._simulation_settings.IgnoreSmallHolesMinDiameter
|
|
157
|
+
|
|
158
|
+
@ignore_small_holes_min_diameter.setter
|
|
159
|
+
def ignore_small_holes_min_diameter(self, value):
|
|
160
|
+
self._simulation_settings.IgnoreSmallHolesMinDiameter = self._pedb.edb_value(value).ToString()
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def improved_loss_model(self):
|
|
164
|
+
"""Improved Loss Model on power ground nets option.
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
str
|
|
169
|
+
``Level1``, ``Level2``, ``Level3``
|
|
170
|
+
"""
|
|
171
|
+
return self._simulation_settings.ImprovedLossModel
|
|
172
|
+
|
|
173
|
+
@improved_loss_model.setter
|
|
174
|
+
def improved_loss_model(self, value):
|
|
175
|
+
expected_values = ["Level1", "Level2", "Level3"]
|
|
176
|
+
if isinstance(value, str) and value in expected_values:
|
|
177
|
+
self._simulation_settings.ImprovedLossModel = value
|
|
178
|
+
else:
|
|
179
|
+
self.logger.error(
|
|
180
|
+
"Property improved_loss_model expects a string value among "
|
|
181
|
+
f"'Level1', 'Level2' or 'Level3' while the provided value is {value}."
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def include_enhanced_bond_wire_modeling(self):
|
|
186
|
+
"""Enhance Bond wire modeling.
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
bool
|
|
191
|
+
"""
|
|
192
|
+
return self._simulation_settings.IncludeEnhancedBondWireModeling
|
|
193
|
+
|
|
194
|
+
@include_enhanced_bond_wire_modeling.setter
|
|
195
|
+
def include_enhanced_bond_wire_modeling(self, value):
|
|
196
|
+
if isinstance(value, bool):
|
|
197
|
+
self._simulation_settings.IncludeEnhancedBondWireModeling = value
|
|
198
|
+
else:
|
|
199
|
+
self.logger.error(
|
|
200
|
+
"Property include_enhanced_bond_wire_modeling expects a "
|
|
201
|
+
f"boolean value while the provided value is {value}."
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def include_nets(self):
|
|
206
|
+
"""Add Additional Nets for simulation.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
[str]
|
|
211
|
+
List of net name.
|
|
212
|
+
"""
|
|
213
|
+
return list(self._simulation_settings.IncludeNets)
|
|
214
|
+
|
|
215
|
+
@include_nets.setter
|
|
216
|
+
def include_nets(self, value):
|
|
217
|
+
if isinstance(value, str):
|
|
218
|
+
value = [value]
|
|
219
|
+
if isinstance(value, list):
|
|
220
|
+
self._simulation_settings.IncludeNets = convert_py_list_to_net_list(value)
|
|
221
|
+
else:
|
|
222
|
+
self.logger.error(
|
|
223
|
+
f"Property include_nets expects a string or list of string while the provided value is {value}."
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def min_plane_area_to_mesh(self):
|
|
228
|
+
"""The minimum area below which geometry is ignored.
|
|
229
|
+
|
|
230
|
+
Returns
|
|
231
|
+
-------
|
|
232
|
+
str
|
|
233
|
+
"""
|
|
234
|
+
return self._simulation_settings.MinPlaneAreaToMesh
|
|
235
|
+
|
|
236
|
+
@min_plane_area_to_mesh.setter
|
|
237
|
+
def min_plane_area_to_mesh(self, value):
|
|
238
|
+
self._simulation_settings.MinPlaneAreaToMesh = self._pedb.edb_value(value).ToString()
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def min_void_area_to_mesh(self):
|
|
242
|
+
"""The minimum area below which voids are ignored.
|
|
243
|
+
|
|
244
|
+
Returns
|
|
245
|
+
-------
|
|
246
|
+
str
|
|
247
|
+
"""
|
|
248
|
+
return self._simulation_settings.MinVoidAreaToMesh
|
|
249
|
+
|
|
250
|
+
@min_void_area_to_mesh.setter
|
|
251
|
+
def min_void_area_to_mesh(self, value):
|
|
252
|
+
self._simulation_settings.MinVoidAreaToMesh = self._pedb.edb_value(value).ToString()
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def model_type(self):
|
|
256
|
+
"""Model Type setting.
|
|
257
|
+
|
|
258
|
+
Returns
|
|
259
|
+
-------
|
|
260
|
+
int
|
|
261
|
+
Model type: ``0``=RDL, ``1``=Package, ``2``=PCB
|
|
262
|
+
"""
|
|
263
|
+
return self._simulation_settings.ModelType
|
|
264
|
+
|
|
265
|
+
@model_type.setter
|
|
266
|
+
def model_type(self, value):
|
|
267
|
+
if isinstance(value, int) and value in range(3):
|
|
268
|
+
self._simulation_settings.ModelType = value
|
|
269
|
+
else:
|
|
270
|
+
self.logger.error(
|
|
271
|
+
f"Property model_type expects an integer value among 0, 1 or 2 while the provided value is {value}."
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def perform_erc(self):
|
|
276
|
+
"""Perform ERC
|
|
277
|
+
|
|
278
|
+
Returns
|
|
279
|
+
-------
|
|
280
|
+
bool
|
|
281
|
+
"""
|
|
282
|
+
return self._simulation_settings.PerformERC
|
|
283
|
+
|
|
284
|
+
@perform_erc.setter
|
|
285
|
+
def perform_erc(self, value):
|
|
286
|
+
if isinstance(value, bool):
|
|
287
|
+
self._simulation_settings.PerformERC = value
|
|
288
|
+
else:
|
|
289
|
+
self.logger.error(f"Property perform_erc expects a boolean value while the provided value is {value}.")
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def pi_slider_pos(self):
|
|
293
|
+
"""The Simulation Preference Slider setting
|
|
294
|
+
|
|
295
|
+
Returns
|
|
296
|
+
-------
|
|
297
|
+
int
|
|
298
|
+
Model type: ``0``= balanced, ``1``=Accuracy.
|
|
299
|
+
"""
|
|
300
|
+
return self._simulation_settings.PISliderPos
|
|
301
|
+
|
|
302
|
+
@pi_slider_pos.setter
|
|
303
|
+
def pi_slider_pos(self, value):
|
|
304
|
+
if isinstance(value, int) and value in range(2):
|
|
305
|
+
self._simulation_settings.PISliderPos = value
|
|
306
|
+
else:
|
|
307
|
+
self.logger.error(
|
|
308
|
+
f"Property pi_slider_pos expects an integer value among 0 or 1 while the provided value is {value}."
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def rms_surface_roughness(self):
|
|
313
|
+
"""RMS Surface Roughness setting
|
|
314
|
+
|
|
315
|
+
Returns
|
|
316
|
+
-------
|
|
317
|
+
str
|
|
318
|
+
"""
|
|
319
|
+
return self._simulation_settings.RMSSurfaceRoughness
|
|
320
|
+
|
|
321
|
+
@rms_surface_roughness.setter
|
|
322
|
+
def rms_surface_roughness(self, value):
|
|
323
|
+
self._simulation_settings.RMSSurfaceRoughness = self._pedb.edb_value(value).ToString()
|
|
324
|
+
|
|
325
|
+
@property
|
|
326
|
+
def signal_nets_conductor_modeling(self):
|
|
327
|
+
"""Conductor Modeling
|
|
328
|
+
|
|
329
|
+
Returns
|
|
330
|
+
-------
|
|
331
|
+
str
|
|
332
|
+
Value: ``"MeshInside"`` or ``"ImpedanceBoundary"``.
|
|
333
|
+
"""
|
|
334
|
+
return self._simulation_settings.SignalNetsConductorModeling
|
|
335
|
+
|
|
336
|
+
@signal_nets_conductor_modeling.setter
|
|
337
|
+
def signal_nets_conductor_modeling(self, value):
|
|
338
|
+
expected_values = ["MeshInside", "ImpedanceBoundary"]
|
|
339
|
+
if isinstance(value, str) and value in expected_values:
|
|
340
|
+
self._simulation_settings.SignalNetsConductorModeling = value
|
|
341
|
+
else:
|
|
342
|
+
self.logger.error(
|
|
343
|
+
"Property signal_nets_conductor_modeling expects a string value among "
|
|
344
|
+
f"'MeshInside' or 'ImpedanceBoundary' while the provided value is {value}."
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
@property
|
|
348
|
+
def signal_nets_error_tolerance(self):
|
|
349
|
+
"""Error Tolerance
|
|
350
|
+
|
|
351
|
+
Returns
|
|
352
|
+
-------
|
|
353
|
+
str
|
|
354
|
+
Value between 0.02 and 1.
|
|
355
|
+
"""
|
|
356
|
+
return self._simulation_settings.SignalNetsErrorTolerance
|
|
357
|
+
|
|
358
|
+
@signal_nets_error_tolerance.setter
|
|
359
|
+
def signal_nets_error_tolerance(self, value):
|
|
360
|
+
self._simulation_settings.SignalNetsErrorTolerance = self._pedb.edb_value(value).ToString()
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def signal_nets_include_improved_dielectric_fill_refinement(self):
|
|
364
|
+
return self._simulation_settings.SignalNetsIncludeImprovedDielectricFillRefinement
|
|
365
|
+
|
|
366
|
+
@signal_nets_include_improved_dielectric_fill_refinement.setter
|
|
367
|
+
def signal_nets_include_improved_dielectric_fill_refinement(self, value):
|
|
368
|
+
if isinstance(value, bool):
|
|
369
|
+
self._simulation_settings.SignalNetsIncludeImprovedDielectricFillRefinement = value
|
|
370
|
+
else:
|
|
371
|
+
self.logger.error(
|
|
372
|
+
"Property signal_nets_include_improved_dielectric_fill_refinement "
|
|
373
|
+
f"expects a boolean value while the provided value is {value}."
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def signal_nets_include_improved_loss_handling(self):
|
|
378
|
+
"""Improved Dielectric Fill Refinement choice.
|
|
379
|
+
|
|
380
|
+
Returns
|
|
381
|
+
-------
|
|
382
|
+
bool
|
|
383
|
+
"""
|
|
384
|
+
return self._simulation_settings.SignalNetsIncludeImprovedLossHandling
|
|
385
|
+
|
|
386
|
+
@signal_nets_include_improved_loss_handling.setter
|
|
387
|
+
def signal_nets_include_improved_loss_handling(self, value):
|
|
388
|
+
if isinstance(value, bool):
|
|
389
|
+
self._simulation_settings.SignalNetsIncludeImprovedLossHandling = value
|
|
390
|
+
else:
|
|
391
|
+
self.logger.error(
|
|
392
|
+
"Property signal_nets_include_improved_loss_handling "
|
|
393
|
+
f"expects a boolean value while the provided value is {value}."
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
@property
|
|
397
|
+
def snap_length_threshold(self):
|
|
398
|
+
return self._simulation_settings.SnapLengthThreshold
|
|
399
|
+
|
|
400
|
+
@snap_length_threshold.setter
|
|
401
|
+
def snap_length_threshold(self, value):
|
|
402
|
+
self._simulation_settings.SnapLengthThreshold = self._pedb.edb_value(value).ToString()
|
|
403
|
+
|
|
404
|
+
@property
|
|
405
|
+
def surface_roughness_model(self):
|
|
406
|
+
"""Chosen Model setting
|
|
407
|
+
|
|
408
|
+
Returns
|
|
409
|
+
-------
|
|
410
|
+
str
|
|
411
|
+
Model allowed, ``"None"``, ``"Exponential"`` or ``"Hammerstad"``.
|
|
412
|
+
"""
|
|
413
|
+
return self._simulation_settings.SurfaceRoughnessModel
|
|
414
|
+
|
|
415
|
+
@surface_roughness_model.setter
|
|
416
|
+
def surface_roughness_model(self, value):
|
|
417
|
+
expected_values = ["None", "Exponential", "Hammerstad"]
|
|
418
|
+
if isinstance(value, str) and value in expected_values:
|
|
419
|
+
self._simulation_settings.SurfaceRoughnessModel = value
|
|
420
|
+
else:
|
|
421
|
+
self.logger.error(
|
|
422
|
+
"Property surface_roughness_model expects a string value among "
|
|
423
|
+
f"'None', 'Exponential' or 'Hammerstad' while the provided value is {value}."
|
|
424
|
+
)
|
pyedb/dotnet/edb_core/siwave.py
CHANGED
|
@@ -43,6 +43,7 @@ from pyedb.dotnet.edb_core.edb_data.sources import (
|
|
|
43
43
|
from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
44
44
|
from pyedb.generic.constants import SolverType, SweepType
|
|
45
45
|
from pyedb.generic.general_methods import _retry_ntimes, generate_unique_name
|
|
46
|
+
from pyedb.misc.siw_feature_config.xtalk_scan.scan_config import SiwaveScanConfig
|
|
46
47
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
47
48
|
|
|
48
49
|
|
|
@@ -1488,6 +1489,19 @@ class EdbSiwave(object):
|
|
|
1488
1489
|
_, value = cell.GetProductProperty(siwave_id, 422, "")
|
|
1489
1490
|
return bool(value)
|
|
1490
1491
|
|
|
1492
|
+
def create_impedance_crosstalk_scan(self, scan_type="impedance"):
|
|
1493
|
+
"""Create Siwave crosstalk scan object
|
|
1494
|
+
|
|
1495
|
+
Parameters
|
|
1496
|
+
----------
|
|
1497
|
+
scan_type : str
|
|
1498
|
+
Scan type to be analyzed. 3 options are available, ``impedance`` for frequency impedance scan,
|
|
1499
|
+
``frequency_xtalk`` for frequency domain crosstalk and ``time_xtalk`` for time domain crosstalk.
|
|
1500
|
+
Default value is ``frequency``.
|
|
1501
|
+
|
|
1502
|
+
"""
|
|
1503
|
+
return SiwaveScanConfig(self._pedb, scan_type)
|
|
1504
|
+
|
|
1491
1505
|
@icepak_use_minimal_comp_defaults.setter
|
|
1492
1506
|
def icepak_use_minimal_comp_defaults(self, value):
|
|
1493
1507
|
value = "True" if bool(value) else ""
|
|
@@ -37,6 +37,10 @@ from pyedb.dotnet.edb_core.sim_setup_data.data.settings import (
|
|
|
37
37
|
ViaSettings,
|
|
38
38
|
)
|
|
39
39
|
from pyedb.dotnet.edb_core.sim_setup_data.data.sim_setup_info import SimSetupInfo
|
|
40
|
+
from pyedb.dotnet.edb_core.sim_setup_data.data.simulation_settings import (
|
|
41
|
+
HFSSPISimulationSettings,
|
|
42
|
+
)
|
|
43
|
+
from pyedb.dotnet.edb_core.sim_setup_data.data.sweep_data import SweepData
|
|
40
44
|
from pyedb.dotnet.edb_core.utilities.simulation_setup import SimulationSetup
|
|
41
45
|
from pyedb.generic.general_methods import generate_unique_name
|
|
42
46
|
|
|
@@ -384,3 +388,82 @@ class HfssSimulationSetup(SimulationSetup):
|
|
|
384
388
|
): # pragma no cover
|
|
385
389
|
return False
|
|
386
390
|
return True
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class HFSSPISimulationSetup(SimulationSetup):
|
|
394
|
+
"""Manages EDB methods for HFSSPI simulation setup."""
|
|
395
|
+
|
|
396
|
+
def __init__(self, pedb, edb_object=None):
|
|
397
|
+
super().__init__(pedb, edb_object)
|
|
398
|
+
self._edb_object = edb_object
|
|
399
|
+
self._pedb = pedb
|
|
400
|
+
self._setup_type = "kHFSSPI"
|
|
401
|
+
self._edb_setup_info = None
|
|
402
|
+
self.logger = self._pedb.logger
|
|
403
|
+
|
|
404
|
+
def create(self, name=None):
|
|
405
|
+
"""Create an HFSS setup."""
|
|
406
|
+
self._name = name
|
|
407
|
+
self._create(name=name, simulation_setup_type=self._setup_type)
|
|
408
|
+
return self
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def setup_type(self):
|
|
412
|
+
return self._setup_type
|
|
413
|
+
|
|
414
|
+
@property
|
|
415
|
+
def settings(self):
|
|
416
|
+
return HFSSPISimulationSettings(self._edb_setup_info, self._pedb, self._edb_object)
|
|
417
|
+
|
|
418
|
+
@property
|
|
419
|
+
def enabled(self):
|
|
420
|
+
return self.settings.enabled
|
|
421
|
+
|
|
422
|
+
@enabled.setter
|
|
423
|
+
def enabled(self, value):
|
|
424
|
+
if isinstance(value, bool):
|
|
425
|
+
self.settings.enabled = value
|
|
426
|
+
else:
|
|
427
|
+
self.logger.error(f"Property enabled expects a boolean value while the provided value is {value}.")
|
|
428
|
+
|
|
429
|
+
@property
|
|
430
|
+
def position(self):
|
|
431
|
+
return self._edb_setup_info.Position
|
|
432
|
+
|
|
433
|
+
@position.setter
|
|
434
|
+
def position(self, value):
|
|
435
|
+
if isinstance(value, int):
|
|
436
|
+
self._edb_setup_info.Position = value
|
|
437
|
+
else:
|
|
438
|
+
self.logger.error(f"Property position expects an integer value while the provided value is {value}.")
|
|
439
|
+
|
|
440
|
+
def add_frequency_sweep(self, name=None, frequency_sweep=None):
|
|
441
|
+
"""Add frequency sweep.
|
|
442
|
+
|
|
443
|
+
Parameters
|
|
444
|
+
----------
|
|
445
|
+
name : str, optional
|
|
446
|
+
Name of the frequency sweep.
|
|
447
|
+
frequency_sweep : list, optional
|
|
448
|
+
List of frequency points.
|
|
449
|
+
|
|
450
|
+
Returns
|
|
451
|
+
-------
|
|
452
|
+
:class:`pyedb.dotnet.edb_core.edb_data.hfss_simulation_setup_data.EdbFrequencySweep`wheen succeeded, ``False``
|
|
453
|
+
when failed.
|
|
454
|
+
|
|
455
|
+
Examples
|
|
456
|
+
--------
|
|
457
|
+
>>> setup1 = edbapp.create_hfss_setup("setup1")
|
|
458
|
+
>>> setup1.add_frequency_sweep(frequency_sweep=[
|
|
459
|
+
... ["linear count", "0", "1kHz", 1],
|
|
460
|
+
... ["log scale", "1kHz", "0.1GHz", 10],
|
|
461
|
+
... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
|
|
462
|
+
... ])
|
|
463
|
+
"""
|
|
464
|
+
if name in self.frequency_sweeps:
|
|
465
|
+
self.logger.error("Frequency sweep with same name already defined.")
|
|
466
|
+
return False
|
|
467
|
+
if not name:
|
|
468
|
+
name = generate_unique_name("sweep")
|
|
469
|
+
return SweepData(self, frequency_sweep, name)
|
|
@@ -100,7 +100,11 @@ class SimulationSetup(object):
|
|
|
100
100
|
|
|
101
101
|
@property
|
|
102
102
|
def sim_setup_info(self):
|
|
103
|
-
|
|
103
|
+
if self._edb_object:
|
|
104
|
+
if self._edb_object.GetType().ToString() not in ["kHFSSPI", "kRaptorX"]:
|
|
105
|
+
return SimSetupInfo(self._pedb, sim_setup=self, edb_object=self._edb_object.GetSimSetupInfo())
|
|
106
|
+
elif self._edb_setup_info:
|
|
107
|
+
return SimSetupInfo(self._pedb, sim_setup=self, edb_object=self._edb_setup_info)
|
|
104
108
|
|
|
105
109
|
@sim_setup_info.setter
|
|
106
110
|
def sim_setup_info(self, sim_setup_info):
|
|
@@ -145,15 +149,14 @@ class SimulationSetup(object):
|
|
|
145
149
|
"kAnalysisOption": None,
|
|
146
150
|
"kSIwaveDCIR": utility.SIWaveDCIRSimulationSetup,
|
|
147
151
|
"kSIwaveEMI": None,
|
|
148
|
-
"kHFSSPI": None,
|
|
149
152
|
"kDDRwizard": None,
|
|
150
153
|
"kQ3D": None,
|
|
151
154
|
"kNumSetupTypes": None,
|
|
152
155
|
}
|
|
153
156
|
|
|
154
|
-
|
|
155
|
-
if int(version[0]) == 2024 and int(version[1]) == 2 or int(version[0]) > 2024:
|
|
157
|
+
if float(self._pedb.edbversion) >= 2024.2:
|
|
156
158
|
setup_type_mapping["kRaptorX"] = utility.RaptorXSimulationSetup
|
|
159
|
+
if float(self._pedb.edbversion) >= 2025.1:
|
|
157
160
|
setup_type_mapping["kHFSSPI"] = utility.HFSSPISimulationSetup
|
|
158
161
|
sim_setup_type = self.sim_setup_info.sim_setup_type
|
|
159
162
|
setup_utility = setup_type_mapping[sim_setup_type.ToString()]
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from pyedb.generic.general_methods import ET
|
|
24
|
+
from pyedb.misc.siw_feature_config.xtalk_scan.net import SingleEndedNet
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CrosstalkFrequency:
|
|
28
|
+
"""Siwave frequency domain crosstalk configuration handler."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, pedb):
|
|
31
|
+
self._pedb = pedb
|
|
32
|
+
self.min_transmission_line_segment_length = "0.25mm"
|
|
33
|
+
self.frequency = "2e9Hz"
|
|
34
|
+
self.nets = {}
|
|
35
|
+
|
|
36
|
+
def extend_xml(self, parent):
|
|
37
|
+
"""Write class xml section.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
parent : :class xml.etree.cElementTree object
|
|
42
|
+
Parent object.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
freq_scan = ET.SubElement(parent, "FdXtalkConfig")
|
|
46
|
+
freq_scan.set("MinTlineSegmentLength", self.min_transmission_line_segment_length)
|
|
47
|
+
freq_scan.set("XtalkFrequency", self.frequency)
|
|
48
|
+
nets = ET.SubElement(freq_scan, "SingleEndedNets")
|
|
49
|
+
for net in list(self.nets.values()):
|
|
50
|
+
net.extend_xml(nets)
|
|
51
|
+
|
|
52
|
+
def add_single_ended_net(
|
|
53
|
+
self,
|
|
54
|
+
name,
|
|
55
|
+
next_warning_threshold=5.0,
|
|
56
|
+
next_violation_threshold=10.0,
|
|
57
|
+
fext_warning_threshold_warning=5.0,
|
|
58
|
+
fext_violation_threshold=5.0,
|
|
59
|
+
):
|
|
60
|
+
"""Add single ended net.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
name : str
|
|
65
|
+
Net name.
|
|
66
|
+
next_warning_threshold : flot or str
|
|
67
|
+
Near end crosstalk warning threshold value. Default value is ``5.0``.
|
|
68
|
+
next_violation_threshold : float, str
|
|
69
|
+
Near end crosstalk violation threshold value. Default value is ``10.0
|
|
70
|
+
|
|
71
|
+
fext_violation_threshold : float, str
|
|
72
|
+
Far end crosstalk violation threshold value, Default value is ``5.0``
|
|
73
|
+
fext_warning_threshold_warning : float, str
|
|
74
|
+
Far end crosstalk warning threshold value, Default value is ``5.0``
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
bool
|
|
79
|
+
"""
|
|
80
|
+
if name and name not in self.nets:
|
|
81
|
+
net = SingleEndedNet()
|
|
82
|
+
net.name = name
|
|
83
|
+
net.next_warning_threshold = next_warning_threshold
|
|
84
|
+
net.next_violation_threshold = next_violation_threshold
|
|
85
|
+
net.fext_warning_threshold = fext_warning_threshold_warning
|
|
86
|
+
net.fext_violation_threshold = fext_violation_threshold
|
|
87
|
+
self.nets[name] = net
|
|
88
|
+
return True
|
|
89
|
+
else:
|
|
90
|
+
self._pedb.logger.error(f"Net {name} already assigned.")
|
|
91
|
+
return False
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from pyedb.generic.general_methods import ET
|
|
24
|
+
from pyedb.misc.siw_feature_config.xtalk_scan.net import SingleEndedNet
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ImpedanceScan:
|
|
28
|
+
def __init__(self, pedb):
|
|
29
|
+
self._pedb = pedb
|
|
30
|
+
self.min_transmission_line_segment_length = "0.25mm"
|
|
31
|
+
self.frequency = "2e9Hz"
|
|
32
|
+
self.nets = {}
|
|
33
|
+
|
|
34
|
+
def extend_xml(self, parent):
|
|
35
|
+
"""Write object wml section"""
|
|
36
|
+
z_scan = ET.SubElement(parent, "Z0ScanConfig")
|
|
37
|
+
z_scan.set("MinTlineSegmentLength", self.min_transmission_line_segment_length)
|
|
38
|
+
z_scan.set("Z0Frequency", self.frequency)
|
|
39
|
+
single_ended_nets = ET.SubElement(z_scan, "SingleEndedNets")
|
|
40
|
+
for net in list(self.nets.values()):
|
|
41
|
+
net.extend_xml(single_ended_nets)
|
|
42
|
+
|
|
43
|
+
def add_single_ended_net(self, name, nominal_impedance=50.0, warning_threshold=17.0, violation_threshold=32.0):
|
|
44
|
+
"""Add single ended net.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
name : str
|
|
49
|
+
Net name.
|
|
50
|
+
nominal_impedance : flot or str
|
|
51
|
+
nominal impedance in ohm. Default value is ``50,0``..
|
|
52
|
+
warning_threshold : float, str
|
|
53
|
+
Warning threshold value. Default value is ``17.0
|
|
54
|
+
violation_threshold : float, str
|
|
55
|
+
Violation threshold value, Default value is ``5.0``
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
bool
|
|
60
|
+
"""
|
|
61
|
+
if name and name not in self.nets:
|
|
62
|
+
net = SingleEndedNet()
|
|
63
|
+
net.name = name
|
|
64
|
+
net.nominal_impedance = nominal_impedance
|
|
65
|
+
net.warning_threshold = warning_threshold
|
|
66
|
+
net.violation_threshold = violation_threshold
|
|
67
|
+
self.nets[name] = net
|
|
68
|
+
else:
|
|
69
|
+
self._pedb.logger.error(f"Net {name} already assigned")
|
|
70
|
+
return False
|